xref: /onnv-gate/usr/src/lib/libstmf/common/stmf.c (revision 10691)
17836SJohn.Forte@Sun.COM /*
27836SJohn.Forte@Sun.COM  * CDDL HEADER START
37836SJohn.Forte@Sun.COM  *
47836SJohn.Forte@Sun.COM  * The contents of this file are subject to the terms of the
57836SJohn.Forte@Sun.COM  * Common Development and Distribution License (the "License").
67836SJohn.Forte@Sun.COM  * You may not use this file except in compliance with the License.
77836SJohn.Forte@Sun.COM  *
87836SJohn.Forte@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97836SJohn.Forte@Sun.COM  * or http://www.opensolaris.org/os/licensing.
107836SJohn.Forte@Sun.COM  * See the License for the specific language governing permissions
117836SJohn.Forte@Sun.COM  * and limitations under the License.
127836SJohn.Forte@Sun.COM  *
137836SJohn.Forte@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
147836SJohn.Forte@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157836SJohn.Forte@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
167836SJohn.Forte@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
177836SJohn.Forte@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
187836SJohn.Forte@Sun.COM  *
197836SJohn.Forte@Sun.COM  * CDDL HEADER END
207836SJohn.Forte@Sun.COM  */
217836SJohn.Forte@Sun.COM /*
229585STim.Szeto@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237836SJohn.Forte@Sun.COM  * Use is subject to license terms.
247836SJohn.Forte@Sun.COM  */
257836SJohn.Forte@Sun.COM 
267836SJohn.Forte@Sun.COM #include <stdlib.h>
277836SJohn.Forte@Sun.COM #include <stdio.h>
287836SJohn.Forte@Sun.COM #include <wchar.h>
297836SJohn.Forte@Sun.COM #include <strings.h>
307836SJohn.Forte@Sun.COM #include <sys/types.h>
317836SJohn.Forte@Sun.COM #include <sys/stat.h>
327836SJohn.Forte@Sun.COM #include <fcntl.h>
337836SJohn.Forte@Sun.COM #include <unistd.h>
347836SJohn.Forte@Sun.COM #include <libintl.h>
357836SJohn.Forte@Sun.COM #include <errno.h>
367836SJohn.Forte@Sun.COM #include <string.h>
377836SJohn.Forte@Sun.COM #include <assert.h>
387836SJohn.Forte@Sun.COM #include <libnvpair.h>
397836SJohn.Forte@Sun.COM #include <pthread.h>
407836SJohn.Forte@Sun.COM #include <syslog.h>
417836SJohn.Forte@Sun.COM #include <libstmf.h>
427836SJohn.Forte@Sun.COM #include <netinet/in.h>
437836SJohn.Forte@Sun.COM #include <inttypes.h>
447836SJohn.Forte@Sun.COM #include <store.h>
457836SJohn.Forte@Sun.COM #include <locale.h>
469585STim.Szeto@Sun.COM #include <math.h>
479585STim.Szeto@Sun.COM #include <libstmf_impl.h>
487836SJohn.Forte@Sun.COM #include <sys/stmf_ioctl.h>
499585STim.Szeto@Sun.COM #include <sys/stmf_sbd_ioctl.h>
507836SJohn.Forte@Sun.COM 
517836SJohn.Forte@Sun.COM #define	STMF_PATH    "/devices/pseudo/stmf@0:admin"
529585STim.Szeto@Sun.COM #define	SBD_PATH    "/devices/pseudo/stmf_sbd@0:admin"
537836SJohn.Forte@Sun.COM 
547836SJohn.Forte@Sun.COM #define	EUI "eui."
557836SJohn.Forte@Sun.COM #define	WWN "wwn."
567836SJohn.Forte@Sun.COM #define	IQN "iqn."
579585STim.Szeto@Sun.COM #define	LU_ASCII_GUID_SIZE 32
589585STim.Szeto@Sun.COM #define	LU_GUID_SIZE 16
599585STim.Szeto@Sun.COM #define	OUI_ASCII_SIZE 6
609585STim.Szeto@Sun.COM #define	OUI_SIZE 3
617836SJohn.Forte@Sun.COM #define	IDENT_LENGTH_BYTE 3
627836SJohn.Forte@Sun.COM 
639585STim.Szeto@Sun.COM /* various initial allocation values */
649585STim.Szeto@Sun.COM #define	ALLOC_LU		8192
659585STim.Szeto@Sun.COM #define	ALLOC_TARGET_PORT	2048
669585STim.Szeto@Sun.COM #define	ALLOC_PROVIDER		64
679585STim.Szeto@Sun.COM #define	ALLOC_GROUP		2048
689585STim.Szeto@Sun.COM #define	ALLOC_SESSION		2048
699585STim.Szeto@Sun.COM #define	ALLOC_VE		256
709585STim.Szeto@Sun.COM #define	ALLOC_PP_DATA_SIZE	128*1024
719585STim.Szeto@Sun.COM #define	ALLOC_GRP_MEMBER	256
729585STim.Szeto@Sun.COM 
737836SJohn.Forte@Sun.COM #define	MAX_ISCSI_NAME	223
749585STim.Szeto@Sun.COM #define	MAX_SERIAL_SIZE 252 + 1
759585STim.Szeto@Sun.COM #define	MAX_LU_ALIAS_SIZE 256
769585STim.Szeto@Sun.COM #define	MAX_SBD_PROPS	MAXPATHLEN + MAX_SERIAL_SIZE + MAX_LU_ALIAS_SIZE
777836SJohn.Forte@Sun.COM 
787836SJohn.Forte@Sun.COM #define	OPEN_STMF 0
797836SJohn.Forte@Sun.COM #define	OPEN_EXCL_STMF O_EXCL
807836SJohn.Forte@Sun.COM 
819585STim.Szeto@Sun.COM #define	OPEN_SBD 0
829585STim.Szeto@Sun.COM #define	OPEN_EXCL_SBD O_EXCL
839585STim.Szeto@Sun.COM 
847836SJohn.Forte@Sun.COM #define	LOGICAL_UNIT_TYPE 0
857836SJohn.Forte@Sun.COM #define	TARGET_TYPE 1
867836SJohn.Forte@Sun.COM #define	STMF_SERVICE_TYPE 2
877836SJohn.Forte@Sun.COM 
889585STim.Szeto@Sun.COM #define	HOST_GROUP   1
899585STim.Szeto@Sun.COM #define	TARGET_GROUP 2
909585STim.Szeto@Sun.COM 
919585STim.Szeto@Sun.COM /* set default persistence here */
929585STim.Szeto@Sun.COM #define	STMF_DEFAULT_PERSIST	STMF_PERSIST_SMF
939585STim.Szeto@Sun.COM 
949585STim.Szeto@Sun.COM #define	MAX_PROVIDER_RETRY 30
959585STim.Szeto@Sun.COM 
967836SJohn.Forte@Sun.COM static int openStmf(int, int *fd);
979585STim.Szeto@Sun.COM static int openSbd(int, int *fd);
987836SJohn.Forte@Sun.COM static int groupIoctl(int fd, int cmd, stmfGroupName *);
997836SJohn.Forte@Sun.COM static int loadStore(int fd);
1007836SJohn.Forte@Sun.COM static int initializeConfig();
1017836SJohn.Forte@Sun.COM static int groupMemberIoctl(int fd, int cmd, stmfGroupName *, stmfDevid *);
1027836SJohn.Forte@Sun.COM static int guidCompare(const void *, const void *);
1037836SJohn.Forte@Sun.COM static int addViewEntryIoctl(int fd, stmfGuid *, stmfViewEntry *);
1047836SJohn.Forte@Sun.COM static int loadHostGroups(int fd, stmfGroupList *);
1057836SJohn.Forte@Sun.COM static int loadTargetGroups(int fd, stmfGroupList *);
1067836SJohn.Forte@Sun.COM static int getStmfState(stmf_state_desc_t *);
1077836SJohn.Forte@Sun.COM static int setStmfState(int fd, stmf_state_desc_t *, int);
1089585STim.Szeto@Sun.COM static int setProviderData(int fd, char *, nvlist_t *, int, uint64_t *);
1099585STim.Szeto@Sun.COM static int createDiskResource(luResourceImpl *);
1109585STim.Szeto@Sun.COM static int createDiskLu(diskResource *, stmfGuid *);
1119585STim.Szeto@Sun.COM static int deleteDiskLu(stmfGuid *luGuid);
1129585STim.Szeto@Sun.COM static int getDiskProp(luResourceImpl *, uint32_t, char *, size_t *);
1139585STim.Szeto@Sun.COM static int getDiskAllProps(stmfGuid *luGuid, luResource *hdl);
1149585STim.Szeto@Sun.COM static int loadDiskPropsFromDriver(luResourceImpl *, sbd_lu_props_t *);
1159585STim.Szeto@Sun.COM static int removeGuidFromDiskStore(stmfGuid *);
1169585STim.Szeto@Sun.COM static int addGuidToDiskStore(stmfGuid *, char *);
1179585STim.Szeto@Sun.COM static int persistDiskGuid(stmfGuid *, char *, boolean_t);
1189585STim.Szeto@Sun.COM static int setDiskProp(luResourceImpl *, uint32_t, const char *);
1199585STim.Szeto@Sun.COM static int checkHexUpper(char *);
1209585STim.Szeto@Sun.COM static int strToShift(const char *);
1219585STim.Szeto@Sun.COM static int niceStrToNum(const char *, uint64_t *);
1229585STim.Szeto@Sun.COM static void diskError(uint32_t, int *);
1239585STim.Szeto@Sun.COM static int importDiskLu(char *fname, stmfGuid *);
1249585STim.Szeto@Sun.COM static int modifyDiskLu(diskResource *, stmfGuid *, const char *);
1259585STim.Szeto@Sun.COM static int modifyDiskLuProp(stmfGuid *, const char *, uint32_t, const char *);
1269585STim.Szeto@Sun.COM static int validateModifyDiskProp(uint32_t);
1279585STim.Szeto@Sun.COM static uint8_t iGetPersistMethod();
1289585STim.Szeto@Sun.COM static int groupListIoctl(stmfGroupList **, int);
1299585STim.Szeto@Sun.COM static int iLoadGroupFromPs(stmfGroupList **, int);
1309585STim.Szeto@Sun.COM static int groupMemberListIoctl(stmfGroupName *, stmfGroupProperties **, int);
1319585STim.Szeto@Sun.COM static int getProviderData(char *, nvlist_t **, int, uint64_t *);
1329585STim.Szeto@Sun.COM static int viewEntryCompare(const void *, const void *);
1339585STim.Szeto@Sun.COM 
1349585STim.Szeto@Sun.COM static pthread_mutex_t persistenceTypeLock = PTHREAD_MUTEX_INITIALIZER;
1359585STim.Szeto@Sun.COM static int iPersistType = 0;
1369585STim.Szeto@Sun.COM /* when B_TRUE, no need to access SMF anymore. Just use iPersistType */
1379585STim.Szeto@Sun.COM static boolean_t iLibSetPersist = B_FALSE;
1387836SJohn.Forte@Sun.COM 
1397836SJohn.Forte@Sun.COM /*
1407836SJohn.Forte@Sun.COM  * Open for stmf module
1417836SJohn.Forte@Sun.COM  *
1427836SJohn.Forte@Sun.COM  * flag - open flag (OPEN_STMF, OPEN_EXCL_STMF)
1437836SJohn.Forte@Sun.COM  * fd - pointer to integer. On success, contains the stmf file descriptor
1447836SJohn.Forte@Sun.COM  */
1457836SJohn.Forte@Sun.COM static int
1467836SJohn.Forte@Sun.COM openStmf(int flag, int *fd)
1477836SJohn.Forte@Sun.COM {
1487836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_ERROR;
1497836SJohn.Forte@Sun.COM 
1507836SJohn.Forte@Sun.COM 	if ((*fd = open(STMF_PATH, O_NDELAY | O_RDONLY | flag)) != -1) {
1517836SJohn.Forte@Sun.COM 		ret = STMF_STATUS_SUCCESS;
1527836SJohn.Forte@Sun.COM 	} else {
1537836SJohn.Forte@Sun.COM 		if (errno == EBUSY) {
1547836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
1559585STim.Szeto@Sun.COM 		} else if (errno == EACCES) {
1569585STim.Szeto@Sun.COM 			ret = STMF_ERROR_PERM;
1577836SJohn.Forte@Sun.COM 		} else {
1587836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
1597836SJohn.Forte@Sun.COM 		}
1607836SJohn.Forte@Sun.COM 		syslog(LOG_DEBUG, "openStmf:open failure:%s:errno(%d)",
1617836SJohn.Forte@Sun.COM 		    STMF_PATH, errno);
1627836SJohn.Forte@Sun.COM 	}
1637836SJohn.Forte@Sun.COM 
1647836SJohn.Forte@Sun.COM 	return (ret);
1657836SJohn.Forte@Sun.COM }
1667836SJohn.Forte@Sun.COM 
1677836SJohn.Forte@Sun.COM /*
1689585STim.Szeto@Sun.COM  * Open for sbd module
1699585STim.Szeto@Sun.COM  *
1709585STim.Szeto@Sun.COM  * flag - open flag (OPEN_STMF, OPEN_EXCL_STMF)
1719585STim.Szeto@Sun.COM  * fd - pointer to integer. On success, contains the stmf file descriptor
1729585STim.Szeto@Sun.COM  */
1739585STim.Szeto@Sun.COM static int
1749585STim.Szeto@Sun.COM openSbd(int flag, int *fd)
1759585STim.Szeto@Sun.COM {
1769585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_ERROR;
1779585STim.Szeto@Sun.COM 
1789585STim.Szeto@Sun.COM 	if ((*fd = open(SBD_PATH, O_NDELAY | O_RDONLY | flag)) != -1) {
1799585STim.Szeto@Sun.COM 		ret = STMF_STATUS_SUCCESS;
1809585STim.Szeto@Sun.COM 	} else {
1819585STim.Szeto@Sun.COM 		if (errno == EBUSY) {
1829585STim.Szeto@Sun.COM 			ret = STMF_ERROR_BUSY;
1839585STim.Szeto@Sun.COM 		} else if (errno == EACCES) {
1849585STim.Szeto@Sun.COM 			ret = STMF_ERROR_PERM;
1859585STim.Szeto@Sun.COM 		} else {
1869585STim.Szeto@Sun.COM 			ret = STMF_STATUS_ERROR;
1879585STim.Szeto@Sun.COM 		}
1889585STim.Szeto@Sun.COM 		syslog(LOG_DEBUG, "openSbd:open failure:%s:errno(%d)",
1899585STim.Szeto@Sun.COM 		    SBD_PATH, errno);
1909585STim.Szeto@Sun.COM 	}
1919585STim.Szeto@Sun.COM 
1929585STim.Szeto@Sun.COM 	return (ret);
1939585STim.Szeto@Sun.COM }
1949585STim.Szeto@Sun.COM 
1959585STim.Szeto@Sun.COM /*
1967836SJohn.Forte@Sun.COM  * initializeConfig
1977836SJohn.Forte@Sun.COM  *
1987836SJohn.Forte@Sun.COM  * This routine should be called before any ioctl requiring initialization
1997836SJohn.Forte@Sun.COM  * which is basically everything except stmfGetState(), setStmfState() and
2007836SJohn.Forte@Sun.COM  * stmfLoadConfig().
2017836SJohn.Forte@Sun.COM  */
2027836SJohn.Forte@Sun.COM static int
2037836SJohn.Forte@Sun.COM initializeConfig()
2047836SJohn.Forte@Sun.COM {
2057836SJohn.Forte@Sun.COM 	int ret;
2067836SJohn.Forte@Sun.COM 	stmfState state;
2077836SJohn.Forte@Sun.COM 
2087836SJohn.Forte@Sun.COM 
2097836SJohn.Forte@Sun.COM 	ret = stmfGetState(&state);
2107836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
2117836SJohn.Forte@Sun.COM 		return (ret);
2127836SJohn.Forte@Sun.COM 	}
2137836SJohn.Forte@Sun.COM 
2147836SJohn.Forte@Sun.COM 	/* if we've already initialized or in the process, return success */
2157836SJohn.Forte@Sun.COM 	if (state.configState == STMF_CONFIG_STATE_INIT_DONE ||
2167836SJohn.Forte@Sun.COM 	    state.configState == STMF_CONFIG_STATE_INIT) {
2177836SJohn.Forte@Sun.COM 		return (STMF_STATUS_SUCCESS);
2187836SJohn.Forte@Sun.COM 	}
2197836SJohn.Forte@Sun.COM 
2207836SJohn.Forte@Sun.COM 	ret = stmfLoadConfig();
2217836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
2227836SJohn.Forte@Sun.COM 		syslog(LOG_DEBUG,
2237836SJohn.Forte@Sun.COM 		    "initializeConfig:stmfLoadConfig:error(%d)", ret);
2247836SJohn.Forte@Sun.COM 		return (ret);
2257836SJohn.Forte@Sun.COM 	}
2267836SJohn.Forte@Sun.COM 
2277836SJohn.Forte@Sun.COM 	ret = stmfGetState(&state);
2287836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
2297836SJohn.Forte@Sun.COM 		syslog(LOG_DEBUG,
2307836SJohn.Forte@Sun.COM 		    "initializeConfig:stmfGetState:error(%d)", ret);
2317836SJohn.Forte@Sun.COM 		return (ret);
2327836SJohn.Forte@Sun.COM 	}
2337836SJohn.Forte@Sun.COM 
2347836SJohn.Forte@Sun.COM 	if (state.configState != STMF_CONFIG_STATE_INIT_DONE) {
2357836SJohn.Forte@Sun.COM 		syslog(LOG_DEBUG, "initializeConfig:state.configState(%d)",
2367836SJohn.Forte@Sun.COM 		    state.configState);
2377836SJohn.Forte@Sun.COM 		ret = STMF_STATUS_ERROR;
2387836SJohn.Forte@Sun.COM 	}
2397836SJohn.Forte@Sun.COM 
2407836SJohn.Forte@Sun.COM 	return (ret);
2417836SJohn.Forte@Sun.COM }
2427836SJohn.Forte@Sun.COM 
2437836SJohn.Forte@Sun.COM 
2447836SJohn.Forte@Sun.COM /*
2457836SJohn.Forte@Sun.COM  * groupIoctl
2467836SJohn.Forte@Sun.COM  *
2477836SJohn.Forte@Sun.COM  * Purpose: issue ioctl for create/delete on group
2487836SJohn.Forte@Sun.COM  *
2497836SJohn.Forte@Sun.COM  * cmd - valid STMF ioctl group cmd
2507836SJohn.Forte@Sun.COM  * groupName - groupName to create or delete
2517836SJohn.Forte@Sun.COM  */
2527836SJohn.Forte@Sun.COM static int
2537836SJohn.Forte@Sun.COM groupIoctl(int fd, int cmd, stmfGroupName *groupName)
2547836SJohn.Forte@Sun.COM {
2557836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
2567836SJohn.Forte@Sun.COM 	int ioctlRet;
2577836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
2587836SJohn.Forte@Sun.COM 	stmf_group_name_t iGroupName;
2597836SJohn.Forte@Sun.COM 
2607836SJohn.Forte@Sun.COM 	bzero(&iGroupName, sizeof (iGroupName));
2617836SJohn.Forte@Sun.COM 
2627836SJohn.Forte@Sun.COM 	bcopy(groupName, &iGroupName.name, strlen((char *)groupName));
2637836SJohn.Forte@Sun.COM 
2647836SJohn.Forte@Sun.COM 	iGroupName.name_size = strlen((char *)groupName);
2657836SJohn.Forte@Sun.COM 
2667836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
2677836SJohn.Forte@Sun.COM 	/*
2687836SJohn.Forte@Sun.COM 	 * Issue ioctl to create the host group
2697836SJohn.Forte@Sun.COM 	 */
2707836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
2717836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (iGroupName);
2727836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&iGroupName;
2737836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
2747836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
2757836SJohn.Forte@Sun.COM 		switch (errno) {
2769585STim.Szeto@Sun.COM 			case EPERM:
2777836SJohn.Forte@Sun.COM 			case EACCES:
2787836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
2797836SJohn.Forte@Sun.COM 				break;
2807836SJohn.Forte@Sun.COM 			default:
2817836SJohn.Forte@Sun.COM 				switch (stmfIoctl.stmf_error) {
2827836SJohn.Forte@Sun.COM 					case STMF_IOCERR_TG_EXISTS:
2837836SJohn.Forte@Sun.COM 					case STMF_IOCERR_HG_EXISTS:
2847836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_EXISTS;
2857836SJohn.Forte@Sun.COM 						break;
2867836SJohn.Forte@Sun.COM 					case STMF_IOCERR_TG_IN_USE:
2877836SJohn.Forte@Sun.COM 					case STMF_IOCERR_HG_IN_USE:
2887836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_GROUP_IN_USE;
2897836SJohn.Forte@Sun.COM 						break;
2907836SJohn.Forte@Sun.COM 					case STMF_IOCERR_INVALID_HG:
2917836SJohn.Forte@Sun.COM 					case STMF_IOCERR_INVALID_TG:
2927836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_NOT_FOUND;
2937836SJohn.Forte@Sun.COM 						break;
2947836SJohn.Forte@Sun.COM 					default:
2957836SJohn.Forte@Sun.COM 						syslog(LOG_DEBUG,
2967836SJohn.Forte@Sun.COM 						    "groupIoctl:error(%d)",
2977836SJohn.Forte@Sun.COM 						    stmfIoctl.stmf_error);
2987836SJohn.Forte@Sun.COM 						ret = STMF_STATUS_ERROR;
2997836SJohn.Forte@Sun.COM 						break;
3007836SJohn.Forte@Sun.COM 				}
3017836SJohn.Forte@Sun.COM 				break;
3027836SJohn.Forte@Sun.COM 		}
3037836SJohn.Forte@Sun.COM 	}
3047836SJohn.Forte@Sun.COM done:
3057836SJohn.Forte@Sun.COM 	return (ret);
3067836SJohn.Forte@Sun.COM }
3077836SJohn.Forte@Sun.COM 
3087836SJohn.Forte@Sun.COM /*
3099585STim.Szeto@Sun.COM  * groupMemberIoctl
3107836SJohn.Forte@Sun.COM  *
3117836SJohn.Forte@Sun.COM  * Purpose: issue ioctl for add/remove member on group
3127836SJohn.Forte@Sun.COM  *
3137836SJohn.Forte@Sun.COM  * cmd - valid STMF ioctl group member cmd
3147836SJohn.Forte@Sun.COM  * groupName - groupName to add to or remove from
3157836SJohn.Forte@Sun.COM  * devid - group member to add or remove
3167836SJohn.Forte@Sun.COM  */
3177836SJohn.Forte@Sun.COM static int
3187836SJohn.Forte@Sun.COM groupMemberIoctl(int fd, int cmd, stmfGroupName *groupName, stmfDevid *devid)
3197836SJohn.Forte@Sun.COM {
3207836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
3217836SJohn.Forte@Sun.COM 	int ioctlRet;
3227836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
3237836SJohn.Forte@Sun.COM 	stmf_group_op_data_t stmfGroupData;
3247836SJohn.Forte@Sun.COM 
3257836SJohn.Forte@Sun.COM 	bzero(&stmfGroupData, sizeof (stmfGroupData));
3267836SJohn.Forte@Sun.COM 
3277836SJohn.Forte@Sun.COM 	bcopy(groupName, &stmfGroupData.group.name, strlen((char *)groupName));
3287836SJohn.Forte@Sun.COM 
3297836SJohn.Forte@Sun.COM 	stmfGroupData.group.name_size = strlen((char *)groupName);
3307836SJohn.Forte@Sun.COM 	stmfGroupData.ident[IDENT_LENGTH_BYTE] = devid->identLength;
3317836SJohn.Forte@Sun.COM 	bcopy(&(devid->ident), &stmfGroupData.ident[IDENT_LENGTH_BYTE + 1],
3327836SJohn.Forte@Sun.COM 	    devid->identLength);
3337836SJohn.Forte@Sun.COM 
3347836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
3357836SJohn.Forte@Sun.COM 	/*
3367836SJohn.Forte@Sun.COM 	 * Issue ioctl to add to the host group
3377836SJohn.Forte@Sun.COM 	 */
3387836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
3397836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (stmfGroupData);
3407836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&stmfGroupData;
3417836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
3427836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
3437836SJohn.Forte@Sun.COM 		switch (errno) {
3447836SJohn.Forte@Sun.COM 			case EBUSY:
3459884STim.Szeto@Sun.COM 				switch (stmfIoctl.stmf_error) {
3469884STim.Szeto@Sun.COM 					case STMF_IOCERR_TG_NEED_TG_OFFLINE:
3479884STim.Szeto@Sun.COM 						ret = STMF_ERROR_TG_ONLINE;
3489884STim.Szeto@Sun.COM 						break;
3499884STim.Szeto@Sun.COM 					default:
3509884STim.Szeto@Sun.COM 						ret = STMF_ERROR_BUSY;
3519884STim.Szeto@Sun.COM 						break;
3529884STim.Szeto@Sun.COM 				}
3537836SJohn.Forte@Sun.COM 				break;
3549585STim.Szeto@Sun.COM 			case EPERM:
3557836SJohn.Forte@Sun.COM 			case EACCES:
3567836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
3577836SJohn.Forte@Sun.COM 				break;
3587836SJohn.Forte@Sun.COM 			default:
3597836SJohn.Forte@Sun.COM 				switch (stmfIoctl.stmf_error) {
3607836SJohn.Forte@Sun.COM 					case STMF_IOCERR_TG_ENTRY_EXISTS:
3617836SJohn.Forte@Sun.COM 					case STMF_IOCERR_HG_ENTRY_EXISTS:
3627836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_EXISTS;
3637836SJohn.Forte@Sun.COM 						break;
3647836SJohn.Forte@Sun.COM 					case STMF_IOCERR_INVALID_TG_ENTRY:
3657836SJohn.Forte@Sun.COM 					case STMF_IOCERR_INVALID_HG_ENTRY:
3667836SJohn.Forte@Sun.COM 						ret =
3677836SJohn.Forte@Sun.COM 						    STMF_ERROR_MEMBER_NOT_FOUND;
3687836SJohn.Forte@Sun.COM 						break;
3697836SJohn.Forte@Sun.COM 					case STMF_IOCERR_INVALID_TG:
3707836SJohn.Forte@Sun.COM 					case STMF_IOCERR_INVALID_HG:
3717836SJohn.Forte@Sun.COM 						ret =
3727836SJohn.Forte@Sun.COM 						    STMF_ERROR_GROUP_NOT_FOUND;
3737836SJohn.Forte@Sun.COM 						break;
3747836SJohn.Forte@Sun.COM 					default:
3757836SJohn.Forte@Sun.COM 						syslog(LOG_DEBUG,
3767836SJohn.Forte@Sun.COM 						    "groupMemberIoctl:error"
3777836SJohn.Forte@Sun.COM 						    "(%d)",
3787836SJohn.Forte@Sun.COM 						    stmfIoctl.stmf_error);
3797836SJohn.Forte@Sun.COM 						ret = STMF_STATUS_ERROR;
3807836SJohn.Forte@Sun.COM 						break;
3817836SJohn.Forte@Sun.COM 				}
3827836SJohn.Forte@Sun.COM 				break;
3837836SJohn.Forte@Sun.COM 		}
3847836SJohn.Forte@Sun.COM 	}
3857836SJohn.Forte@Sun.COM done:
3867836SJohn.Forte@Sun.COM 	return (ret);
3877836SJohn.Forte@Sun.COM }
3887836SJohn.Forte@Sun.COM 
3897836SJohn.Forte@Sun.COM /*
3909585STim.Szeto@Sun.COM  * qsort function
3919585STim.Szeto@Sun.COM  * sort on veIndex
3929585STim.Szeto@Sun.COM  */
3939585STim.Szeto@Sun.COM static int
3949585STim.Szeto@Sun.COM viewEntryCompare(const void *p1, const void *p2)
3959585STim.Szeto@Sun.COM {
3969585STim.Szeto@Sun.COM 
3979585STim.Szeto@Sun.COM 	stmfViewEntry *v1 = (stmfViewEntry *)p1, *v2 = (stmfViewEntry *)p2;
3989585STim.Szeto@Sun.COM 	if (v1->veIndex > v2->veIndex)
3999585STim.Szeto@Sun.COM 		return (1);
4009585STim.Szeto@Sun.COM 	if (v1->veIndex < v2->veIndex)
4019585STim.Szeto@Sun.COM 		return (-1);
4029585STim.Szeto@Sun.COM 	return (0);
4039585STim.Szeto@Sun.COM }
4049585STim.Szeto@Sun.COM 
4059585STim.Szeto@Sun.COM /*
4067836SJohn.Forte@Sun.COM  * guidCompare
4077836SJohn.Forte@Sun.COM  *
4087836SJohn.Forte@Sun.COM  * qsort function
4097836SJohn.Forte@Sun.COM  * sort on guid
4107836SJohn.Forte@Sun.COM  */
4117836SJohn.Forte@Sun.COM static int
4127836SJohn.Forte@Sun.COM guidCompare(const void *p1, const void *p2)
4137836SJohn.Forte@Sun.COM {
4147836SJohn.Forte@Sun.COM 
4157836SJohn.Forte@Sun.COM 	stmfGuid *g1 = (stmfGuid *)p1, *g2 = (stmfGuid *)p2;
4167836SJohn.Forte@Sun.COM 	int i;
4177836SJohn.Forte@Sun.COM 
4187836SJohn.Forte@Sun.COM 	for (i = 0; i < sizeof (stmfGuid); i++) {
4197836SJohn.Forte@Sun.COM 		if (g1->guid[i] > g2->guid[i])
4207836SJohn.Forte@Sun.COM 			return (1);
4217836SJohn.Forte@Sun.COM 		if (g1->guid[i] < g2->guid[i])
4227836SJohn.Forte@Sun.COM 			return (-1);
4237836SJohn.Forte@Sun.COM 	}
4247836SJohn.Forte@Sun.COM 
4257836SJohn.Forte@Sun.COM 	return (0);
4267836SJohn.Forte@Sun.COM }
4277836SJohn.Forte@Sun.COM 
4287836SJohn.Forte@Sun.COM /*
4297836SJohn.Forte@Sun.COM  * stmfAddToHostGroup
4307836SJohn.Forte@Sun.COM  *
4317836SJohn.Forte@Sun.COM  * Purpose: Adds an initiator to an existing host group
4327836SJohn.Forte@Sun.COM  *
4337836SJohn.Forte@Sun.COM  * hostGroupName - name of an existing host group
4347836SJohn.Forte@Sun.COM  * hostName - name of initiator to add
4357836SJohn.Forte@Sun.COM  */
4367836SJohn.Forte@Sun.COM int
4377836SJohn.Forte@Sun.COM stmfAddToHostGroup(stmfGroupName *hostGroupName, stmfDevid *hostName)
4387836SJohn.Forte@Sun.COM {
4397836SJohn.Forte@Sun.COM 	int ret;
4407836SJohn.Forte@Sun.COM 	int fd;
4417836SJohn.Forte@Sun.COM 
4427836SJohn.Forte@Sun.COM 	if (hostGroupName == NULL ||
4437836SJohn.Forte@Sun.COM 	    (strnlen((char *)hostGroupName, sizeof (stmfGroupName))
4447836SJohn.Forte@Sun.COM 	    == sizeof (stmfGroupName)) || hostName == NULL) {
4457836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
4467836SJohn.Forte@Sun.COM 	}
4477836SJohn.Forte@Sun.COM 
4487836SJohn.Forte@Sun.COM 	/* call init */
4497836SJohn.Forte@Sun.COM 	ret = initializeConfig();
4507836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
4517836SJohn.Forte@Sun.COM 		return (ret);
4527836SJohn.Forte@Sun.COM 	}
4537836SJohn.Forte@Sun.COM 
4547836SJohn.Forte@Sun.COM 	/*
4557836SJohn.Forte@Sun.COM 	 * Open control node for stmf
4567836SJohn.Forte@Sun.COM 	 */
4577836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
4587836SJohn.Forte@Sun.COM 		return (ret);
4597836SJohn.Forte@Sun.COM 
4607836SJohn.Forte@Sun.COM 	if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_HG_ENTRY, hostGroupName,
4617836SJohn.Forte@Sun.COM 	    hostName)) != STMF_STATUS_SUCCESS) {
4627836SJohn.Forte@Sun.COM 		goto done;
4637836SJohn.Forte@Sun.COM 	}
4647836SJohn.Forte@Sun.COM 
4659585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
4669585STim.Szeto@Sun.COM 		goto done;
4679585STim.Szeto@Sun.COM 	}
4689585STim.Szeto@Sun.COM 
4697836SJohn.Forte@Sun.COM 	ret = psAddHostGroupMember((char *)hostGroupName,
4707836SJohn.Forte@Sun.COM 	    (char *)hostName->ident);
4717836SJohn.Forte@Sun.COM 	switch (ret) {
4727836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
4737836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
4747836SJohn.Forte@Sun.COM 			break;
4757836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_EXISTS:
4767836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_EXISTS;
4777836SJohn.Forte@Sun.COM 			break;
4787836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_GROUP_NOT_FOUND:
4797836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_GROUP_NOT_FOUND;
4807836SJohn.Forte@Sun.COM 			break;
4817836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
4827836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
4837836SJohn.Forte@Sun.COM 			break;
4847836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
4857836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
4867836SJohn.Forte@Sun.COM 			break;
4877836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
4887836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
4897836SJohn.Forte@Sun.COM 			break;
4907836SJohn.Forte@Sun.COM 		default:
4917836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
4927836SJohn.Forte@Sun.COM 			    "stmfAddToHostGroup:psAddHostGroupMember:error(%d)",
4937836SJohn.Forte@Sun.COM 			    ret);
4947836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
4957836SJohn.Forte@Sun.COM 			break;
4967836SJohn.Forte@Sun.COM 	}
4977836SJohn.Forte@Sun.COM 
4987836SJohn.Forte@Sun.COM done:
4997836SJohn.Forte@Sun.COM 	(void) close(fd);
5007836SJohn.Forte@Sun.COM 	return (ret);
5017836SJohn.Forte@Sun.COM }
5027836SJohn.Forte@Sun.COM 
5037836SJohn.Forte@Sun.COM /*
5047836SJohn.Forte@Sun.COM  * stmfAddToTargetGroup
5057836SJohn.Forte@Sun.COM  *
5067836SJohn.Forte@Sun.COM  * Purpose: Adds a local port to an existing target group
5077836SJohn.Forte@Sun.COM  *
5087836SJohn.Forte@Sun.COM  * targetGroupName - name of an existing target group
5097836SJohn.Forte@Sun.COM  * targetName - name of target to add
5107836SJohn.Forte@Sun.COM  */
5117836SJohn.Forte@Sun.COM int
5127836SJohn.Forte@Sun.COM stmfAddToTargetGroup(stmfGroupName *targetGroupName, stmfDevid *targetName)
5137836SJohn.Forte@Sun.COM {
5147836SJohn.Forte@Sun.COM 	int ret;
5157836SJohn.Forte@Sun.COM 	int fd;
5167836SJohn.Forte@Sun.COM 
5177836SJohn.Forte@Sun.COM 	if (targetGroupName == NULL ||
5187836SJohn.Forte@Sun.COM 	    (strnlen((char *)targetGroupName, sizeof (stmfGroupName))
5197836SJohn.Forte@Sun.COM 	    == sizeof (stmfGroupName)) || targetName == NULL) {
5207836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
5217836SJohn.Forte@Sun.COM 	}
5227836SJohn.Forte@Sun.COM 
5237836SJohn.Forte@Sun.COM 	/* call init */
5247836SJohn.Forte@Sun.COM 	ret = initializeConfig();
5257836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
5267836SJohn.Forte@Sun.COM 		return (ret);
5277836SJohn.Forte@Sun.COM 	}
5287836SJohn.Forte@Sun.COM 
5297836SJohn.Forte@Sun.COM 	/*
5307836SJohn.Forte@Sun.COM 	 * Open control node for stmf
5317836SJohn.Forte@Sun.COM 	 */
5327836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
5337836SJohn.Forte@Sun.COM 		return (ret);
5347836SJohn.Forte@Sun.COM 
5357836SJohn.Forte@Sun.COM 	if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_TG_ENTRY,
5367836SJohn.Forte@Sun.COM 	    targetGroupName, targetName)) != STMF_STATUS_SUCCESS) {
5377836SJohn.Forte@Sun.COM 		goto done;
5387836SJohn.Forte@Sun.COM 	}
5397836SJohn.Forte@Sun.COM 
5409585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
5419585STim.Szeto@Sun.COM 		goto done;
5429585STim.Szeto@Sun.COM 	}
5439585STim.Szeto@Sun.COM 
5447836SJohn.Forte@Sun.COM 	ret = psAddTargetGroupMember((char *)targetGroupName,
5457836SJohn.Forte@Sun.COM 	    (char *)targetName->ident);
5467836SJohn.Forte@Sun.COM 	switch (ret) {
5477836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
5487836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
5497836SJohn.Forte@Sun.COM 			break;
5507836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_EXISTS:
5517836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_EXISTS;
5527836SJohn.Forte@Sun.COM 			break;
5537836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_GROUP_NOT_FOUND:
5547836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_GROUP_NOT_FOUND;
5557836SJohn.Forte@Sun.COM 			break;
5567836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
5577836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
5587836SJohn.Forte@Sun.COM 			break;
5597836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
5607836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
5617836SJohn.Forte@Sun.COM 			break;
5627836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
5637836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
5647836SJohn.Forte@Sun.COM 			break;
5657836SJohn.Forte@Sun.COM 		default:
5667836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
5677836SJohn.Forte@Sun.COM 			    "stmfAddToTargetGroup:psAddTargetGroupMember:"
5687836SJohn.Forte@Sun.COM 			    "error(%d)", ret);
5697836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
5707836SJohn.Forte@Sun.COM 			break;
5717836SJohn.Forte@Sun.COM 	}
5727836SJohn.Forte@Sun.COM 
5737836SJohn.Forte@Sun.COM done:
5747836SJohn.Forte@Sun.COM 	(void) close(fd);
5757836SJohn.Forte@Sun.COM 	return (ret);
5767836SJohn.Forte@Sun.COM }
5777836SJohn.Forte@Sun.COM 
5787836SJohn.Forte@Sun.COM /*
5797836SJohn.Forte@Sun.COM  * addViewEntryIoctl
5807836SJohn.Forte@Sun.COM  *
5817836SJohn.Forte@Sun.COM  * Purpose: Issues ioctl to add a view entry
5827836SJohn.Forte@Sun.COM  *
5837836SJohn.Forte@Sun.COM  * lu - Logical Unit identifier to which the view entry is added
5847836SJohn.Forte@Sun.COM  * viewEntry - view entry to add
5857836SJohn.Forte@Sun.COM  * init - When set to B_TRUE, we are in the init state, i.e. don't call open
5867836SJohn.Forte@Sun.COM  */
5877836SJohn.Forte@Sun.COM static int
5887836SJohn.Forte@Sun.COM addViewEntryIoctl(int fd, stmfGuid *lu, stmfViewEntry *viewEntry)
5897836SJohn.Forte@Sun.COM {
5907836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
5917836SJohn.Forte@Sun.COM 	int ioctlRet;
5927836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
5937836SJohn.Forte@Sun.COM 	stmf_view_op_entry_t ioctlViewEntry;
5947836SJohn.Forte@Sun.COM 
5957836SJohn.Forte@Sun.COM 	bzero(&ioctlViewEntry, sizeof (ioctlViewEntry));
5967836SJohn.Forte@Sun.COM 	/*
5977836SJohn.Forte@Sun.COM 	 * don't set ve_ndx or ve_ndx_valid as ve_ndx_valid should be
5987836SJohn.Forte@Sun.COM 	 * false on input
5997836SJohn.Forte@Sun.COM 	 */
6007836SJohn.Forte@Sun.COM 	ioctlViewEntry.ve_lu_number_valid = viewEntry->luNbrValid;
6017836SJohn.Forte@Sun.COM 	ioctlViewEntry.ve_all_hosts = viewEntry->allHosts;
6027836SJohn.Forte@Sun.COM 	ioctlViewEntry.ve_all_targets = viewEntry->allTargets;
6037836SJohn.Forte@Sun.COM 
6047836SJohn.Forte@Sun.COM 	if (viewEntry->allHosts == B_FALSE) {
6057836SJohn.Forte@Sun.COM 		bcopy(viewEntry->hostGroup, &ioctlViewEntry.ve_host_group.name,
6067836SJohn.Forte@Sun.COM 		    sizeof (stmfGroupName));
6077836SJohn.Forte@Sun.COM 		ioctlViewEntry.ve_host_group.name_size =
6087836SJohn.Forte@Sun.COM 		    strlen((char *)viewEntry->hostGroup);
6097836SJohn.Forte@Sun.COM 	}
6107836SJohn.Forte@Sun.COM 	if (viewEntry->allTargets == B_FALSE) {
6117836SJohn.Forte@Sun.COM 		bcopy(viewEntry->targetGroup,
6127836SJohn.Forte@Sun.COM 		    &ioctlViewEntry.ve_target_group.name,
6137836SJohn.Forte@Sun.COM 		    sizeof (stmfGroupName));
6147836SJohn.Forte@Sun.COM 		ioctlViewEntry.ve_target_group.name_size =
6157836SJohn.Forte@Sun.COM 		    strlen((char *)viewEntry->targetGroup);
6167836SJohn.Forte@Sun.COM 	}
6177836SJohn.Forte@Sun.COM 	if (viewEntry->luNbrValid) {
6187836SJohn.Forte@Sun.COM 		bcopy(viewEntry->luNbr, &ioctlViewEntry.ve_lu_nbr,
6197836SJohn.Forte@Sun.COM 		    sizeof (ioctlViewEntry.ve_lu_nbr));
6207836SJohn.Forte@Sun.COM 	}
6217836SJohn.Forte@Sun.COM 	bcopy(lu, &ioctlViewEntry.ve_guid, sizeof (stmfGuid));
6227836SJohn.Forte@Sun.COM 
6237836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
6247836SJohn.Forte@Sun.COM 	/*
6257836SJohn.Forte@Sun.COM 	 * Issue ioctl to add to the view entry
6267836SJohn.Forte@Sun.COM 	 */
6277836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
6287836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry);
6297836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry;
6307836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = sizeof (ioctlViewEntry);
6317836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&ioctlViewEntry;
6327836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_ADD_VIEW_ENTRY, &stmfIoctl);
6337836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
6347836SJohn.Forte@Sun.COM 		switch (errno) {
6357836SJohn.Forte@Sun.COM 			case EBUSY:
6367836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
6377836SJohn.Forte@Sun.COM 				break;
6389585STim.Szeto@Sun.COM 			case EPERM:
6399585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
6409585STim.Szeto@Sun.COM 				break;
6417836SJohn.Forte@Sun.COM 			case EACCES:
6427836SJohn.Forte@Sun.COM 				switch (stmfIoctl.stmf_error) {
6437836SJohn.Forte@Sun.COM 					case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
6447836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_CONFIG_NONE;
6457836SJohn.Forte@Sun.COM 						break;
6467836SJohn.Forte@Sun.COM 					default:
6477836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_PERM;
6487836SJohn.Forte@Sun.COM 						break;
6497836SJohn.Forte@Sun.COM 				}
6507836SJohn.Forte@Sun.COM 				break;
6517836SJohn.Forte@Sun.COM 			default:
6527836SJohn.Forte@Sun.COM 				switch (stmfIoctl.stmf_error) {
6537836SJohn.Forte@Sun.COM 					case STMF_IOCERR_LU_NUMBER_IN_USE:
6547836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_LUN_IN_USE;
6557836SJohn.Forte@Sun.COM 						break;
6567836SJohn.Forte@Sun.COM 					case STMF_IOCERR_VIEW_ENTRY_CONFLICT:
6577836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_VE_CONFLICT;
6587836SJohn.Forte@Sun.COM 						break;
6597836SJohn.Forte@Sun.COM 					case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
6607836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_CONFIG_NONE;
6617836SJohn.Forte@Sun.COM 						break;
6627836SJohn.Forte@Sun.COM 					case STMF_IOCERR_INVALID_HG:
6637836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_INVALID_HG;
6647836SJohn.Forte@Sun.COM 						break;
6657836SJohn.Forte@Sun.COM 					case STMF_IOCERR_INVALID_TG:
6667836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_INVALID_TG;
6677836SJohn.Forte@Sun.COM 						break;
6687836SJohn.Forte@Sun.COM 					default:
6697836SJohn.Forte@Sun.COM 						syslog(LOG_DEBUG,
6707836SJohn.Forte@Sun.COM 						    "addViewEntryIoctl"
6717836SJohn.Forte@Sun.COM 						    ":error(%d)",
6727836SJohn.Forte@Sun.COM 						    stmfIoctl.stmf_error);
6737836SJohn.Forte@Sun.COM 						ret = STMF_STATUS_ERROR;
6747836SJohn.Forte@Sun.COM 						break;
6757836SJohn.Forte@Sun.COM 				}
6767836SJohn.Forte@Sun.COM 				break;
6777836SJohn.Forte@Sun.COM 		}
6787836SJohn.Forte@Sun.COM 		goto done;
6797836SJohn.Forte@Sun.COM 	}
6807836SJohn.Forte@Sun.COM 
6817836SJohn.Forte@Sun.COM 	/* copy lu nbr back to caller's view entry on success */
6827836SJohn.Forte@Sun.COM 	viewEntry->veIndex = ioctlViewEntry.ve_ndx;
6837836SJohn.Forte@Sun.COM 	if (ioctlViewEntry.ve_lu_number_valid) {
6847836SJohn.Forte@Sun.COM 		bcopy(&ioctlViewEntry.ve_lu_nbr, viewEntry->luNbr,
6857836SJohn.Forte@Sun.COM 		    sizeof (ioctlViewEntry.ve_lu_nbr));
6867836SJohn.Forte@Sun.COM 	}
6877836SJohn.Forte@Sun.COM 	viewEntry->luNbrValid = B_TRUE;
6887836SJohn.Forte@Sun.COM 
6897836SJohn.Forte@Sun.COM done:
6907836SJohn.Forte@Sun.COM 	return (ret);
6917836SJohn.Forte@Sun.COM }
6927836SJohn.Forte@Sun.COM 
6937836SJohn.Forte@Sun.COM /*
6947836SJohn.Forte@Sun.COM  * stmfAddViewEntry
6957836SJohn.Forte@Sun.COM  *
6967836SJohn.Forte@Sun.COM  * Purpose: Adds a view entry to a logical unit
6977836SJohn.Forte@Sun.COM  *
6987836SJohn.Forte@Sun.COM  * lu - guid of the logical unit to which the view entry is added
6997836SJohn.Forte@Sun.COM  * viewEntry - view entry structure to add
7007836SJohn.Forte@Sun.COM  */
7017836SJohn.Forte@Sun.COM int
7027836SJohn.Forte@Sun.COM stmfAddViewEntry(stmfGuid *lu, stmfViewEntry *viewEntry)
7037836SJohn.Forte@Sun.COM {
7047836SJohn.Forte@Sun.COM 	int ret;
7057836SJohn.Forte@Sun.COM 	int fd;
7067836SJohn.Forte@Sun.COM 	stmfViewEntry iViewEntry;
7077836SJohn.Forte@Sun.COM 
7087836SJohn.Forte@Sun.COM 	if (lu == NULL || viewEntry == NULL) {
7097836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
7107836SJohn.Forte@Sun.COM 	}
7117836SJohn.Forte@Sun.COM 
7127836SJohn.Forte@Sun.COM 	/* initialize and set internal view entry */
7137836SJohn.Forte@Sun.COM 	bzero(&iViewEntry, sizeof (iViewEntry));
7147836SJohn.Forte@Sun.COM 
7157836SJohn.Forte@Sun.COM 	if (!viewEntry->allHosts) {
7167836SJohn.Forte@Sun.COM 		bcopy(viewEntry->hostGroup, iViewEntry.hostGroup,
7177836SJohn.Forte@Sun.COM 		    sizeof (iViewEntry.hostGroup));
7187836SJohn.Forte@Sun.COM 	} else {
7197836SJohn.Forte@Sun.COM 		iViewEntry.allHosts = B_TRUE;
7207836SJohn.Forte@Sun.COM 	}
7217836SJohn.Forte@Sun.COM 
7227836SJohn.Forte@Sun.COM 	if (!viewEntry->allTargets) {
7237836SJohn.Forte@Sun.COM 		bcopy(viewEntry->targetGroup, iViewEntry.targetGroup,
7247836SJohn.Forte@Sun.COM 		    sizeof (iViewEntry.targetGroup));
7257836SJohn.Forte@Sun.COM 	} else {
7267836SJohn.Forte@Sun.COM 		iViewEntry.allTargets = B_TRUE;
7277836SJohn.Forte@Sun.COM 	}
7287836SJohn.Forte@Sun.COM 
7297836SJohn.Forte@Sun.COM 	if (viewEntry->luNbrValid) {
7307836SJohn.Forte@Sun.COM 		iViewEntry.luNbrValid = B_TRUE;
7317836SJohn.Forte@Sun.COM 		bcopy(viewEntry->luNbr, iViewEntry.luNbr,
7327836SJohn.Forte@Sun.COM 		    sizeof (iViewEntry.luNbr));
7337836SJohn.Forte@Sun.COM 	}
7347836SJohn.Forte@Sun.COM 
7357836SJohn.Forte@Sun.COM 	/*
7367836SJohn.Forte@Sun.COM 	 * set users return view entry index valid flag to false
7377836SJohn.Forte@Sun.COM 	 * in case of failure
7387836SJohn.Forte@Sun.COM 	 */
7397836SJohn.Forte@Sun.COM 	viewEntry->veIndexValid = B_FALSE;
7407836SJohn.Forte@Sun.COM 
7417836SJohn.Forte@Sun.COM 	/* Check to ensure service exists */
7427836SJohn.Forte@Sun.COM 	if (psCheckService() != STMF_STATUS_SUCCESS) {
7437836SJohn.Forte@Sun.COM 		return (STMF_ERROR_SERVICE_NOT_FOUND);
7447836SJohn.Forte@Sun.COM 	}
7457836SJohn.Forte@Sun.COM 
7467836SJohn.Forte@Sun.COM 	/* call init */
7477836SJohn.Forte@Sun.COM 	ret = initializeConfig();
7487836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
7497836SJohn.Forte@Sun.COM 		return (ret);
7507836SJohn.Forte@Sun.COM 	}
7517836SJohn.Forte@Sun.COM 
7527836SJohn.Forte@Sun.COM 	/*
7537836SJohn.Forte@Sun.COM 	 * Open control node for stmf
7547836SJohn.Forte@Sun.COM 	 */
7557836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
7567836SJohn.Forte@Sun.COM 		return (ret);
7577836SJohn.Forte@Sun.COM 
7587836SJohn.Forte@Sun.COM 	/*
7597836SJohn.Forte@Sun.COM 	 * First add the view entry to the driver
7607836SJohn.Forte@Sun.COM 	 */
7617836SJohn.Forte@Sun.COM 	ret = addViewEntryIoctl(fd, lu, &iViewEntry);
7627836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
7637836SJohn.Forte@Sun.COM 		goto done;
7647836SJohn.Forte@Sun.COM 	}
7657836SJohn.Forte@Sun.COM 
7669585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
7679585STim.Szeto@Sun.COM 		goto done;
7689585STim.Szeto@Sun.COM 	}
7699585STim.Szeto@Sun.COM 
7707836SJohn.Forte@Sun.COM 	/*
7717836SJohn.Forte@Sun.COM 	 * If the add to driver was successful, add it to the persistent
7727836SJohn.Forte@Sun.COM 	 * store.
7737836SJohn.Forte@Sun.COM 	 */
7747836SJohn.Forte@Sun.COM 	ret = psAddViewEntry(lu, &iViewEntry);
7757836SJohn.Forte@Sun.COM 	switch (ret) {
7767836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
7777836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
7787836SJohn.Forte@Sun.COM 			break;
7797836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
7807836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
7817836SJohn.Forte@Sun.COM 			break;
7827836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
7837836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
7847836SJohn.Forte@Sun.COM 			break;
7857836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
7867836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
7877836SJohn.Forte@Sun.COM 			break;
7887836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
7897836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
7907836SJohn.Forte@Sun.COM 			break;
7917836SJohn.Forte@Sun.COM 		default:
7927836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
7937836SJohn.Forte@Sun.COM 			    "stmfAddViewEntry:psAddViewEntry:error(%d)", ret);
7947836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
7957836SJohn.Forte@Sun.COM 			break;
7967836SJohn.Forte@Sun.COM 	}
7977836SJohn.Forte@Sun.COM 
7987836SJohn.Forte@Sun.COM done:
7997836SJohn.Forte@Sun.COM 	(void) close(fd);
8007836SJohn.Forte@Sun.COM 
8017836SJohn.Forte@Sun.COM 	if (ret == STMF_STATUS_SUCCESS) {
8027836SJohn.Forte@Sun.COM 		/* set caller's view entry on success */
8037836SJohn.Forte@Sun.COM 		viewEntry->veIndexValid = iViewEntry.veIndexValid;
8047836SJohn.Forte@Sun.COM 		viewEntry->veIndex = iViewEntry.veIndex;
8057836SJohn.Forte@Sun.COM 		viewEntry->luNbrValid = B_TRUE;
8067836SJohn.Forte@Sun.COM 		bcopy(iViewEntry.luNbr, viewEntry->luNbr,
8077836SJohn.Forte@Sun.COM 		    sizeof (iViewEntry.luNbr));
8087836SJohn.Forte@Sun.COM 	}
8097836SJohn.Forte@Sun.COM 	return (ret);
8107836SJohn.Forte@Sun.COM }
8117836SJohn.Forte@Sun.COM 
8127836SJohn.Forte@Sun.COM /*
8137836SJohn.Forte@Sun.COM  * stmfClearProviderData
8147836SJohn.Forte@Sun.COM  *
8157836SJohn.Forte@Sun.COM  * Purpose: delete all provider data for specified provider
8167836SJohn.Forte@Sun.COM  *
8177836SJohn.Forte@Sun.COM  * providerName - name of provider for which data should be deleted
8187836SJohn.Forte@Sun.COM  */
8197836SJohn.Forte@Sun.COM int
8207836SJohn.Forte@Sun.COM stmfClearProviderData(char *providerName, int providerType)
8217836SJohn.Forte@Sun.COM {
8227836SJohn.Forte@Sun.COM 	int ret;
8237836SJohn.Forte@Sun.COM 	int fd;
8247836SJohn.Forte@Sun.COM 	int ioctlRet;
8257836SJohn.Forte@Sun.COM 	int savedErrno;
8267836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
8277836SJohn.Forte@Sun.COM 	stmf_ppioctl_data_t ppi;
8287836SJohn.Forte@Sun.COM 
8297836SJohn.Forte@Sun.COM 	/* call init */
8307836SJohn.Forte@Sun.COM 	ret = initializeConfig();
8317836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
8327836SJohn.Forte@Sun.COM 		return (ret);
8337836SJohn.Forte@Sun.COM 	}
8347836SJohn.Forte@Sun.COM 
8357836SJohn.Forte@Sun.COM 	if (providerName == NULL) {
8367836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
8377836SJohn.Forte@Sun.COM 	}
8387836SJohn.Forte@Sun.COM 
8397836SJohn.Forte@Sun.COM 	if (providerType != STMF_LU_PROVIDER_TYPE &&
8407836SJohn.Forte@Sun.COM 	    providerType != STMF_PORT_PROVIDER_TYPE) {
8417836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
8427836SJohn.Forte@Sun.COM 	}
8437836SJohn.Forte@Sun.COM 
8447836SJohn.Forte@Sun.COM 	/*
8457836SJohn.Forte@Sun.COM 	 * Open control node for stmf
8467836SJohn.Forte@Sun.COM 	 */
8477836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
8487836SJohn.Forte@Sun.COM 		return (ret);
8497836SJohn.Forte@Sun.COM 
8507836SJohn.Forte@Sun.COM 	bzero(&ppi, sizeof (ppi));
8517836SJohn.Forte@Sun.COM 
8527836SJohn.Forte@Sun.COM 	(void) strncpy(ppi.ppi_name, providerName, sizeof (ppi.ppi_name));
8537836SJohn.Forte@Sun.COM 
8547836SJohn.Forte@Sun.COM 	switch (providerType) {
8557836SJohn.Forte@Sun.COM 		case STMF_LU_PROVIDER_TYPE:
8567836SJohn.Forte@Sun.COM 			ppi.ppi_lu_provider = 1;
8577836SJohn.Forte@Sun.COM 			break;
8587836SJohn.Forte@Sun.COM 		case STMF_PORT_PROVIDER_TYPE:
8597836SJohn.Forte@Sun.COM 			ppi.ppi_port_provider = 1;
8607836SJohn.Forte@Sun.COM 			break;
8617836SJohn.Forte@Sun.COM 		default:
8627836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_INVALID_ARG;
8637836SJohn.Forte@Sun.COM 			goto done;
8647836SJohn.Forte@Sun.COM 	}
8657836SJohn.Forte@Sun.COM 
8667836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
8677836SJohn.Forte@Sun.COM 
8687836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
8697836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (stmf_ppioctl_data_t);
8707836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ppi;
8717836SJohn.Forte@Sun.COM 
8727836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_CLEAR_PP_DATA, &stmfIoctl);
8737836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
8747836SJohn.Forte@Sun.COM 		savedErrno = errno;
8757836SJohn.Forte@Sun.COM 		switch (savedErrno) {
8767836SJohn.Forte@Sun.COM 			case EBUSY:
8777836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
8787836SJohn.Forte@Sun.COM 				break;
8799585STim.Szeto@Sun.COM 			case EPERM:
8807836SJohn.Forte@Sun.COM 			case EACCES:
8817836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
8827836SJohn.Forte@Sun.COM 				break;
8837836SJohn.Forte@Sun.COM 			default:
8847836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
8857836SJohn.Forte@Sun.COM 				    "stmfClearProviderData:ioctl error(%d)",
8867836SJohn.Forte@Sun.COM 				    ioctlRet);
8877836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
8887836SJohn.Forte@Sun.COM 				break;
8897836SJohn.Forte@Sun.COM 		}
8907836SJohn.Forte@Sun.COM 		if (savedErrno != ENOENT) {
8917836SJohn.Forte@Sun.COM 			goto done;
8927836SJohn.Forte@Sun.COM 		}
8937836SJohn.Forte@Sun.COM 	}
8947836SJohn.Forte@Sun.COM 
8959585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
8969585STim.Szeto@Sun.COM 		goto done;
8979585STim.Szeto@Sun.COM 	}
8989585STim.Szeto@Sun.COM 
8997836SJohn.Forte@Sun.COM 	ret = psClearProviderData(providerName, providerType);
9007836SJohn.Forte@Sun.COM 	switch (ret) {
9017836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
9027836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
9037836SJohn.Forte@Sun.COM 			break;
9047836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
9057836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
9067836SJohn.Forte@Sun.COM 			break;
9077836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
9087836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
9097836SJohn.Forte@Sun.COM 			break;
9107836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
9117836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
9127836SJohn.Forte@Sun.COM 			break;
9137836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
9147836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
9157836SJohn.Forte@Sun.COM 			break;
9167836SJohn.Forte@Sun.COM 		default:
9177836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
9187836SJohn.Forte@Sun.COM 			    "stmfClearProviderData:psClearProviderData"
9197836SJohn.Forte@Sun.COM 			    ":error(%d)", ret);
9207836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
9217836SJohn.Forte@Sun.COM 			break;
9227836SJohn.Forte@Sun.COM 	}
9237836SJohn.Forte@Sun.COM 
9247836SJohn.Forte@Sun.COM done:
9257836SJohn.Forte@Sun.COM 	(void) close(fd);
9267836SJohn.Forte@Sun.COM 	return (ret);
9277836SJohn.Forte@Sun.COM }
9287836SJohn.Forte@Sun.COM 
9297836SJohn.Forte@Sun.COM /*
9307836SJohn.Forte@Sun.COM  * stmfCreateHostGroup
9317836SJohn.Forte@Sun.COM  *
9327836SJohn.Forte@Sun.COM  * Purpose: Create a new initiator group
9337836SJohn.Forte@Sun.COM  *
9347836SJohn.Forte@Sun.COM  * hostGroupName - name of host group to create
9357836SJohn.Forte@Sun.COM  */
9367836SJohn.Forte@Sun.COM int
9377836SJohn.Forte@Sun.COM stmfCreateHostGroup(stmfGroupName *hostGroupName)
9387836SJohn.Forte@Sun.COM {
9397836SJohn.Forte@Sun.COM 	int ret;
9407836SJohn.Forte@Sun.COM 	int fd;
9417836SJohn.Forte@Sun.COM 
9427836SJohn.Forte@Sun.COM 	if (hostGroupName == NULL ||
9437836SJohn.Forte@Sun.COM 	    (strnlen((char *)hostGroupName, sizeof (stmfGroupName))
9447836SJohn.Forte@Sun.COM 	    == sizeof (stmfGroupName))) {
9457836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
9467836SJohn.Forte@Sun.COM 	}
9477836SJohn.Forte@Sun.COM 
9487836SJohn.Forte@Sun.COM 	/* Check to ensure service exists */
9497836SJohn.Forte@Sun.COM 	if (psCheckService() != STMF_STATUS_SUCCESS) {
9507836SJohn.Forte@Sun.COM 		return (STMF_ERROR_SERVICE_NOT_FOUND);
9517836SJohn.Forte@Sun.COM 	}
9527836SJohn.Forte@Sun.COM 
9537836SJohn.Forte@Sun.COM 	/* call init */
9547836SJohn.Forte@Sun.COM 	ret = initializeConfig();
9557836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
9567836SJohn.Forte@Sun.COM 		return (ret);
9577836SJohn.Forte@Sun.COM 	}
9587836SJohn.Forte@Sun.COM 
9597836SJohn.Forte@Sun.COM 	/*
9607836SJohn.Forte@Sun.COM 	 * Open control node for stmf
9617836SJohn.Forte@Sun.COM 	 */
9627836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
9637836SJohn.Forte@Sun.COM 		return (ret);
9647836SJohn.Forte@Sun.COM 
9657836SJohn.Forte@Sun.COM 	if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_HOST_GROUP,
9667836SJohn.Forte@Sun.COM 	    hostGroupName)) != STMF_STATUS_SUCCESS) {
9677836SJohn.Forte@Sun.COM 		goto done;
9687836SJohn.Forte@Sun.COM 	}
9697836SJohn.Forte@Sun.COM 
9709585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
9719585STim.Szeto@Sun.COM 		goto done;
9729585STim.Szeto@Sun.COM 	}
9739585STim.Szeto@Sun.COM 
9747836SJohn.Forte@Sun.COM 	ret = psCreateHostGroup((char *)hostGroupName);
9757836SJohn.Forte@Sun.COM 	switch (ret) {
9767836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
9777836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
9787836SJohn.Forte@Sun.COM 			break;
9797836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_EXISTS:
9807836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_EXISTS;
9817836SJohn.Forte@Sun.COM 			break;
9827836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
9837836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
9847836SJohn.Forte@Sun.COM 			break;
9857836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
9867836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
9877836SJohn.Forte@Sun.COM 			break;
9887836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
9897836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
9907836SJohn.Forte@Sun.COM 			break;
9917836SJohn.Forte@Sun.COM 		default:
9927836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
9937836SJohn.Forte@Sun.COM 			    "stmfCreateHostGroup:psCreateHostGroup:error(%d)",
9947836SJohn.Forte@Sun.COM 			    ret);
9957836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
9967836SJohn.Forte@Sun.COM 			break;
9977836SJohn.Forte@Sun.COM 	}
9987836SJohn.Forte@Sun.COM 
9997836SJohn.Forte@Sun.COM done:
10007836SJohn.Forte@Sun.COM 	(void) close(fd);
10017836SJohn.Forte@Sun.COM 	return (ret);
10027836SJohn.Forte@Sun.COM }
10037836SJohn.Forte@Sun.COM 
10047836SJohn.Forte@Sun.COM /*
10059585STim.Szeto@Sun.COM  * stmfCreateLu
10069585STim.Szeto@Sun.COM  *
10079585STim.Szeto@Sun.COM  * Purpose: Create a logical unit
10089585STim.Szeto@Sun.COM  *
10099585STim.Szeto@Sun.COM  * hdl - handle to logical unit resource created via stmfCreateLuResource
10109585STim.Szeto@Sun.COM  *
10119585STim.Szeto@Sun.COM  * luGuid - If non-NULL, on success, contains the guid of the created logical
10129585STim.Szeto@Sun.COM  *	    unit
10139585STim.Szeto@Sun.COM  */
10149585STim.Szeto@Sun.COM int
10159585STim.Szeto@Sun.COM stmfCreateLu(luResource hdl, stmfGuid *luGuid)
10169585STim.Szeto@Sun.COM {
10179585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
10189585STim.Szeto@Sun.COM 	luResourceImpl *luPropsHdl = hdl;
10199585STim.Szeto@Sun.COM 
10209585STim.Szeto@Sun.COM 	if (hdl == NULL) {
10219585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
10229585STim.Szeto@Sun.COM 	}
10239585STim.Szeto@Sun.COM 
10249585STim.Szeto@Sun.COM 	if (luPropsHdl->type == STMF_DISK) {
10259585STim.Szeto@Sun.COM 		ret = createDiskLu((diskResource *)luPropsHdl->resource,
10269585STim.Szeto@Sun.COM 		    luGuid);
10279585STim.Szeto@Sun.COM 	} else {
10289585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
10299585STim.Szeto@Sun.COM 	}
10309585STim.Szeto@Sun.COM 
10319585STim.Szeto@Sun.COM 	return (ret);
10329585STim.Szeto@Sun.COM }
10339585STim.Szeto@Sun.COM 
10349585STim.Szeto@Sun.COM /*
10359585STim.Szeto@Sun.COM  * stmfCreateLuResource
10369585STim.Szeto@Sun.COM  *
10379585STim.Szeto@Sun.COM  * Purpose: Create resource handle for a logical unit
10389585STim.Szeto@Sun.COM  *
10399585STim.Szeto@Sun.COM  * dType - Type of logical unit resource to create
10409585STim.Szeto@Sun.COM  *	   Can be: STMF_DISK
10419585STim.Szeto@Sun.COM  *
10429585STim.Szeto@Sun.COM  * hdl - pointer to luResource
10439585STim.Szeto@Sun.COM  */
10449585STim.Szeto@Sun.COM int
10459585STim.Szeto@Sun.COM stmfCreateLuResource(uint16_t dType, luResource *hdl)
10469585STim.Szeto@Sun.COM {
10479585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
10489585STim.Szeto@Sun.COM 
10499585STim.Szeto@Sun.COM 	if (dType != STMF_DISK || hdl == NULL) {
10509585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
10519585STim.Szeto@Sun.COM 	}
10529585STim.Szeto@Sun.COM 
10539585STim.Szeto@Sun.COM 	*hdl = calloc(1, sizeof (luResourceImpl));
10549585STim.Szeto@Sun.COM 	if (*hdl == NULL) {
10559585STim.Szeto@Sun.COM 		return (STMF_ERROR_NOMEM);
10569585STim.Szeto@Sun.COM 	}
10579585STim.Szeto@Sun.COM 
10589585STim.Szeto@Sun.COM 	ret = createDiskResource((luResourceImpl *)*hdl);
10599585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
10609585STim.Szeto@Sun.COM 		free(*hdl);
10619585STim.Szeto@Sun.COM 		return (ret);
10629585STim.Szeto@Sun.COM 	}
10639585STim.Szeto@Sun.COM 
10649585STim.Szeto@Sun.COM 	return (STMF_STATUS_SUCCESS);
10659585STim.Szeto@Sun.COM }
10669585STim.Szeto@Sun.COM 
10679585STim.Szeto@Sun.COM /*
10689585STim.Szeto@Sun.COM  * Creates a disk logical unit
10699585STim.Szeto@Sun.COM  *
10709585STim.Szeto@Sun.COM  * disk - pointer to diskResource structure that represents the properties
10719585STim.Szeto@Sun.COM  *        for the disk logical unit to be created.
10729585STim.Szeto@Sun.COM  */
10739585STim.Szeto@Sun.COM static int
10749585STim.Szeto@Sun.COM createDiskLu(diskResource *disk, stmfGuid *createdGuid)
10759585STim.Szeto@Sun.COM {
10769585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
10779585STim.Szeto@Sun.COM 	int dataFileNameLen = 0;
10789585STim.Szeto@Sun.COM 	int metaFileNameLen = 0;
10799585STim.Szeto@Sun.COM 	int serialNumLen = 0;
10809585STim.Szeto@Sun.COM 	int luAliasLen = 0;
108110113SNattuvetty.Bhavyan@Sun.COM 	int luMgmtUrlLen = 0;
10829585STim.Szeto@Sun.COM 	int sluBufSize = 0;
10839585STim.Szeto@Sun.COM 	int bufOffset = 0;
10849585STim.Szeto@Sun.COM 	int fd = 0;
10859585STim.Szeto@Sun.COM 	int ioctlRet;
10869585STim.Szeto@Sun.COM 	int savedErrno;
10879585STim.Szeto@Sun.COM 	stmfGuid guid;
10889585STim.Szeto@Sun.COM 	stmf_iocdata_t sbdIoctl = {0};
10899585STim.Szeto@Sun.COM 
10909585STim.Szeto@Sun.COM 	sbd_create_and_reg_lu_t *sbdLu = NULL;
10919585STim.Szeto@Sun.COM 
10929585STim.Szeto@Sun.COM 	/*
10939585STim.Szeto@Sun.COM 	 * Open control node for sbd
10949585STim.Szeto@Sun.COM 	 */
10959585STim.Szeto@Sun.COM 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
10969585STim.Szeto@Sun.COM 		return (ret);
10979585STim.Szeto@Sun.COM 
10989585STim.Szeto@Sun.COM 	/* data file name must be specified */
10999585STim.Szeto@Sun.COM 	if (disk->luDataFileNameValid) {
11009585STim.Szeto@Sun.COM 		dataFileNameLen = strlen(disk->luDataFileName);
11019585STim.Szeto@Sun.COM 	} else {
11029585STim.Szeto@Sun.COM 		(void) close(fd);
11039585STim.Szeto@Sun.COM 		return (STMF_ERROR_MISSING_PROP_VAL);
11049585STim.Szeto@Sun.COM 	}
11059585STim.Szeto@Sun.COM 
11069585STim.Szeto@Sun.COM 	sluBufSize += dataFileNameLen + 1;
11079585STim.Szeto@Sun.COM 
11089585STim.Szeto@Sun.COM 	if (disk->luMetaFileNameValid) {
11099585STim.Szeto@Sun.COM 		metaFileNameLen = strlen(disk->luMetaFileName);
11109585STim.Szeto@Sun.COM 		sluBufSize += metaFileNameLen + 1;
11119585STim.Szeto@Sun.COM 	}
11129585STim.Szeto@Sun.COM 
11139585STim.Szeto@Sun.COM 	serialNumLen = strlen(disk->serialNum);
11149585STim.Szeto@Sun.COM 	sluBufSize += serialNumLen;
11159585STim.Szeto@Sun.COM 
11169585STim.Szeto@Sun.COM 	if (disk->luAliasValid) {
11179585STim.Szeto@Sun.COM 		luAliasLen = strlen(disk->luAlias);
11189585STim.Szeto@Sun.COM 		sluBufSize += luAliasLen + 1;
11199585STim.Szeto@Sun.COM 	}
11209585STim.Szeto@Sun.COM 
112110113SNattuvetty.Bhavyan@Sun.COM 	if (disk->luMgmtUrlValid) {
112210113SNattuvetty.Bhavyan@Sun.COM 		luMgmtUrlLen = strlen(disk->luMgmtUrl);
112310113SNattuvetty.Bhavyan@Sun.COM 		sluBufSize += luMgmtUrlLen + 1;
112410113SNattuvetty.Bhavyan@Sun.COM 	}
112510113SNattuvetty.Bhavyan@Sun.COM 
11269585STim.Szeto@Sun.COM 	/*
11279585STim.Szeto@Sun.COM 	 * 8 is the size of the buffer set aside for
11289585STim.Szeto@Sun.COM 	 * concatenation of variable length fields
11299585STim.Szeto@Sun.COM 	 */
11309585STim.Szeto@Sun.COM 	sbdLu = (sbd_create_and_reg_lu_t *)calloc(1,
11319585STim.Szeto@Sun.COM 	    sizeof (sbd_create_and_reg_lu_t) + sluBufSize - 8);
11329585STim.Szeto@Sun.COM 	if (sbdLu == NULL) {
11339585STim.Szeto@Sun.COM 		return (STMF_ERROR_NOMEM);
11349585STim.Szeto@Sun.COM 	}
11359585STim.Szeto@Sun.COM 
11369585STim.Szeto@Sun.COM 	sbdLu->slu_struct_size = sizeof (sbd_create_and_reg_lu_t) +
11379585STim.Szeto@Sun.COM 	    sluBufSize - 8;
11389585STim.Szeto@Sun.COM 
11399585STim.Szeto@Sun.COM 	if (metaFileNameLen) {
11409585STim.Szeto@Sun.COM 		sbdLu->slu_meta_fname_valid = 1;
11419585STim.Szeto@Sun.COM 		sbdLu->slu_meta_fname_off = bufOffset;
11429585STim.Szeto@Sun.COM 		bcopy(disk->luMetaFileName, &(sbdLu->slu_buf[bufOffset]),
11439585STim.Szeto@Sun.COM 		    metaFileNameLen + 1);
11449585STim.Szeto@Sun.COM 		bufOffset += metaFileNameLen + 1;
11459585STim.Szeto@Sun.COM 	}
11469585STim.Szeto@Sun.COM 
11479585STim.Szeto@Sun.COM 	bcopy(disk->luDataFileName, &(sbdLu->slu_buf[bufOffset]),
11489585STim.Szeto@Sun.COM 	    dataFileNameLen + 1);
11499585STim.Szeto@Sun.COM 	sbdLu->slu_data_fname_off = bufOffset;
11509585STim.Szeto@Sun.COM 	bufOffset += dataFileNameLen + 1;
11519585STim.Szeto@Sun.COM 
11529585STim.Szeto@Sun.COM 	/* currently, serial # is not passed null terminated to the driver */
11539585STim.Szeto@Sun.COM 	if (disk->serialNumValid) {
11549585STim.Szeto@Sun.COM 		sbdLu->slu_serial_valid = 1;
11559585STim.Szeto@Sun.COM 		sbdLu->slu_serial_off = bufOffset;
11569585STim.Szeto@Sun.COM 		sbdLu->slu_serial_size = serialNumLen;
11579585STim.Szeto@Sun.COM 		bcopy(disk->serialNum, &(sbdLu->slu_buf[bufOffset]),
11589585STim.Szeto@Sun.COM 		    serialNumLen);
11599585STim.Szeto@Sun.COM 		bufOffset += serialNumLen;
11609585STim.Szeto@Sun.COM 	}
11619585STim.Szeto@Sun.COM 
11629585STim.Szeto@Sun.COM 	if (disk->luAliasValid) {
11639585STim.Szeto@Sun.COM 		sbdLu->slu_alias_valid = 1;
11649585STim.Szeto@Sun.COM 		sbdLu->slu_alias_off = bufOffset;
11659585STim.Szeto@Sun.COM 		bcopy(disk->luAlias, &(sbdLu->slu_buf[bufOffset]),
11669585STim.Szeto@Sun.COM 		    luAliasLen + 1);
11679585STim.Szeto@Sun.COM 		bufOffset += luAliasLen + 1;
11689585STim.Szeto@Sun.COM 	}
11699585STim.Szeto@Sun.COM 
117010113SNattuvetty.Bhavyan@Sun.COM 	if (disk->luMgmtUrlValid) {
117110113SNattuvetty.Bhavyan@Sun.COM 		sbdLu->slu_mgmt_url_valid = 1;
117210113SNattuvetty.Bhavyan@Sun.COM 		sbdLu->slu_mgmt_url_off = bufOffset;
117310113SNattuvetty.Bhavyan@Sun.COM 		bcopy(disk->luMgmtUrl, &(sbdLu->slu_buf[bufOffset]),
117410113SNattuvetty.Bhavyan@Sun.COM 		    luMgmtUrlLen + 1);
117510113SNattuvetty.Bhavyan@Sun.COM 		bufOffset += luMgmtUrlLen + 1;
117610113SNattuvetty.Bhavyan@Sun.COM 	}
117710113SNattuvetty.Bhavyan@Sun.COM 
11789585STim.Szeto@Sun.COM 	if (disk->luSizeValid) {
11799585STim.Szeto@Sun.COM 		sbdLu->slu_lu_size_valid = 1;
11809585STim.Szeto@Sun.COM 		sbdLu->slu_lu_size = disk->luSize;
11819585STim.Szeto@Sun.COM 	}
11829585STim.Szeto@Sun.COM 
11839585STim.Szeto@Sun.COM 	if (disk->luGuidValid) {
11849585STim.Szeto@Sun.COM 		sbdLu->slu_guid_valid = 1;
11859585STim.Szeto@Sun.COM 		bcopy(disk->luGuid, sbdLu->slu_guid, sizeof (disk->luGuid));
11869585STim.Szeto@Sun.COM 	}
11879585STim.Szeto@Sun.COM 
11889585STim.Szeto@Sun.COM 	if (disk->vidValid) {
11899585STim.Szeto@Sun.COM 		sbdLu->slu_vid_valid = 1;
11909585STim.Szeto@Sun.COM 		bcopy(disk->vid, sbdLu->slu_vid, sizeof (disk->vid));
11919585STim.Szeto@Sun.COM 	}
11929585STim.Szeto@Sun.COM 
11939585STim.Szeto@Sun.COM 	if (disk->pidValid) {
11949585STim.Szeto@Sun.COM 		sbdLu->slu_pid_valid = 1;
11959585STim.Szeto@Sun.COM 		bcopy(disk->pid, sbdLu->slu_pid, sizeof (disk->pid));
11969585STim.Szeto@Sun.COM 	}
11979585STim.Szeto@Sun.COM 
11989585STim.Szeto@Sun.COM 	if (disk->revValid) {
11999585STim.Szeto@Sun.COM 		sbdLu->slu_rev_valid = 1;
12009585STim.Szeto@Sun.COM 		bcopy(disk->rev, sbdLu->slu_rev, sizeof (disk->rev));
12019585STim.Szeto@Sun.COM 	}
12029585STim.Szeto@Sun.COM 
12039585STim.Szeto@Sun.COM 	if (disk->companyIdValid) {
12049585STim.Szeto@Sun.COM 		sbdLu->slu_company_id_valid = 1;
12059585STim.Szeto@Sun.COM 		sbdLu->slu_company_id = disk->companyId;
12069585STim.Szeto@Sun.COM 	}
12079585STim.Szeto@Sun.COM 
12089585STim.Szeto@Sun.COM 	if (disk->blkSizeValid) {
12099585STim.Szeto@Sun.COM 		sbdLu->slu_blksize_valid = 1;
12109585STim.Szeto@Sun.COM 		sbdLu->slu_blksize = disk->blkSize;
12119585STim.Szeto@Sun.COM 	}
12129585STim.Szeto@Sun.COM 
12139585STim.Szeto@Sun.COM 	if (disk->writeProtectEnableValid) {
12149585STim.Szeto@Sun.COM 		if (disk->writeProtectEnable) {
12159585STim.Szeto@Sun.COM 			sbdLu->slu_write_protected = 1;
12169585STim.Szeto@Sun.COM 		}
12179585STim.Szeto@Sun.COM 	}
12189585STim.Szeto@Sun.COM 
12199585STim.Szeto@Sun.COM 	if (disk->writebackCacheDisableValid) {
12209585STim.Szeto@Sun.COM 		sbdLu->slu_writeback_cache_disable_valid = 1;
12219585STim.Szeto@Sun.COM 		if (disk->writebackCacheDisable) {
12229585STim.Szeto@Sun.COM 			sbdLu->slu_writeback_cache_disable = 1;
12239585STim.Szeto@Sun.COM 		}
12249585STim.Szeto@Sun.COM 	}
12259585STim.Szeto@Sun.COM 
12269585STim.Szeto@Sun.COM 	sbdIoctl.stmf_version = STMF_VERSION_1;
12279585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf_size = sbdLu->slu_struct_size;
12289585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdLu;
12299585STim.Szeto@Sun.COM 	sbdIoctl.stmf_obuf_size = sbdLu->slu_struct_size;
12309585STim.Szeto@Sun.COM 	sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdLu;
12319585STim.Szeto@Sun.COM 
12329585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, SBD_IOCTL_CREATE_AND_REGISTER_LU, &sbdIoctl);
12339585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
12349585STim.Szeto@Sun.COM 		savedErrno = errno;
12359585STim.Szeto@Sun.COM 		switch (savedErrno) {
12369585STim.Szeto@Sun.COM 			case EBUSY:
12379585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
12389585STim.Szeto@Sun.COM 				break;
12399585STim.Szeto@Sun.COM 			case EPERM:
12409585STim.Szeto@Sun.COM 			case EACCES:
12419585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
12429585STim.Szeto@Sun.COM 				break;
12439585STim.Szeto@Sun.COM 			default:
12449585STim.Szeto@Sun.COM 				diskError(sbdIoctl.stmf_error, &ret);
12459585STim.Szeto@Sun.COM 				if (ret == STMF_STATUS_ERROR) {
12469585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
12479585STim.Szeto@Sun.COM 					"createDiskLu:ioctl "
12489585STim.Szeto@Sun.COM 					"error(%d) (%d) (%d)", ioctlRet,
12499585STim.Szeto@Sun.COM 					    sbdIoctl.stmf_error, savedErrno);
12509585STim.Szeto@Sun.COM 				}
12519585STim.Szeto@Sun.COM 				break;
12529585STim.Szeto@Sun.COM 		}
12539585STim.Szeto@Sun.COM 	}
12549585STim.Szeto@Sun.COM 
12559585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
12569585STim.Szeto@Sun.COM 		goto done;
12579585STim.Szeto@Sun.COM 	}
12589585STim.Szeto@Sun.COM 
12599585STim.Szeto@Sun.COM 	/*
12609585STim.Szeto@Sun.COM 	 * on success, copy the resulting guid into the caller's guid if not
12619585STim.Szeto@Sun.COM 	 * NULL
12629585STim.Szeto@Sun.COM 	 */
12639585STim.Szeto@Sun.COM 	if (createdGuid) {
12649585STim.Szeto@Sun.COM 		bcopy(sbdLu->slu_guid, createdGuid->guid,
12659585STim.Szeto@Sun.COM 		    sizeof (sbdLu->slu_guid));
12669585STim.Szeto@Sun.COM 	}
12679585STim.Szeto@Sun.COM 
12689585STim.Szeto@Sun.COM 	bcopy(sbdLu->slu_guid, guid.guid, sizeof (sbdLu->slu_guid));
12699585STim.Szeto@Sun.COM 	if (disk->luMetaFileNameValid) {
12709585STim.Szeto@Sun.COM 		ret = addGuidToDiskStore(&guid, disk->luMetaFileName);
12719585STim.Szeto@Sun.COM 	} else {
12729585STim.Szeto@Sun.COM 		ret = addGuidToDiskStore(&guid, disk->luDataFileName);
12739585STim.Szeto@Sun.COM 	}
12749585STim.Szeto@Sun.COM done:
12759585STim.Szeto@Sun.COM 	free(sbdLu);
12769585STim.Szeto@Sun.COM 	(void) close(fd);
12779585STim.Szeto@Sun.COM 	return (ret);
12789585STim.Szeto@Sun.COM }
12799585STim.Szeto@Sun.COM 
12809585STim.Szeto@Sun.COM 
12819585STim.Szeto@Sun.COM /*
12829585STim.Szeto@Sun.COM  * stmfImportLu
12839585STim.Szeto@Sun.COM  *
12849585STim.Szeto@Sun.COM  * Purpose: Import a previously created logical unit
12859585STim.Szeto@Sun.COM  *
12869585STim.Szeto@Sun.COM  * dType - Type of logical unit
12879585STim.Szeto@Sun.COM  *         Can be: STMF_DISK
12889585STim.Szeto@Sun.COM  *
12899585STim.Szeto@Sun.COM  * luGuid - If non-NULL, on success, contains the guid of the imported logical
12909585STim.Szeto@Sun.COM  *	    unit
12919585STim.Szeto@Sun.COM  *
12929585STim.Szeto@Sun.COM  * fname - A file name where the metadata resides
12939585STim.Szeto@Sun.COM  *
12949585STim.Szeto@Sun.COM  */
12959585STim.Szeto@Sun.COM int
12969585STim.Szeto@Sun.COM stmfImportLu(uint16_t dType, char *fname, stmfGuid *luGuid)
12979585STim.Szeto@Sun.COM {
12989585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
12999585STim.Szeto@Sun.COM 
13009585STim.Szeto@Sun.COM 	if (dType == STMF_DISK) {
13019585STim.Szeto@Sun.COM 		ret = importDiskLu(fname, luGuid);
13029585STim.Szeto@Sun.COM 	} else {
13039585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
13049585STim.Szeto@Sun.COM 	}
13059585STim.Szeto@Sun.COM 
13069585STim.Szeto@Sun.COM 	return (ret);
13079585STim.Szeto@Sun.COM }
13089585STim.Szeto@Sun.COM 
13099585STim.Szeto@Sun.COM /*
13109585STim.Szeto@Sun.COM  * importDiskLu
13119585STim.Szeto@Sun.COM  *
13129585STim.Szeto@Sun.COM  * filename - filename to import
13139585STim.Szeto@Sun.COM  * createdGuid - if not NULL, on success contains the imported guid
13149585STim.Szeto@Sun.COM  *
13159585STim.Szeto@Sun.COM  */
13169585STim.Szeto@Sun.COM static int
13179585STim.Szeto@Sun.COM importDiskLu(char *fname, stmfGuid *createdGuid)
13189585STim.Szeto@Sun.COM {
13199585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
13209585STim.Szeto@Sun.COM 	int fd = 0;
13219585STim.Szeto@Sun.COM 	int ioctlRet;
13229585STim.Szeto@Sun.COM 	int savedErrno;
13239585STim.Szeto@Sun.COM 	int metaFileNameLen;
13249585STim.Szeto@Sun.COM 	stmfGuid iGuid;
13259585STim.Szeto@Sun.COM 	int iluBufSize = 0;
13269585STim.Szeto@Sun.COM 	sbd_import_lu_t *sbdLu = NULL;
13279585STim.Szeto@Sun.COM 	stmf_iocdata_t sbdIoctl = {0};
13289585STim.Szeto@Sun.COM 
13299585STim.Szeto@Sun.COM 	if (fname == NULL) {
13309585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
13319585STim.Szeto@Sun.COM 	}
13329585STim.Szeto@Sun.COM 
13339585STim.Szeto@Sun.COM 	/*
13349585STim.Szeto@Sun.COM 	 * Open control node for sbd
13359585STim.Szeto@Sun.COM 	 */
13369585STim.Szeto@Sun.COM 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
13379585STim.Szeto@Sun.COM 		return (ret);
13389585STim.Szeto@Sun.COM 
13399585STim.Szeto@Sun.COM 	metaFileNameLen = strlen(fname);
13409585STim.Szeto@Sun.COM 	iluBufSize += metaFileNameLen + 1;
13419585STim.Szeto@Sun.COM 
13429585STim.Szeto@Sun.COM 	/*
13439585STim.Szeto@Sun.COM 	 * 8 is the size of the buffer set aside for
13449585STim.Szeto@Sun.COM 	 * concatenation of variable length fields
13459585STim.Szeto@Sun.COM 	 */
13469585STim.Szeto@Sun.COM 	sbdLu = (sbd_import_lu_t *)calloc(1,
13479585STim.Szeto@Sun.COM 	    sizeof (sbd_import_lu_t) + iluBufSize - 8);
13489585STim.Szeto@Sun.COM 	if (sbdLu == NULL) {
13499585STim.Szeto@Sun.COM 		(void) close(fd);
13509585STim.Szeto@Sun.COM 		return (STMF_ERROR_NOMEM);
13519585STim.Szeto@Sun.COM 	}
13529585STim.Szeto@Sun.COM 
13539585STim.Szeto@Sun.COM 	/*
13549585STim.Szeto@Sun.COM 	 * Accept either a data file or meta data file.
13559585STim.Szeto@Sun.COM 	 * sbd will do the right thing here either way.
13569585STim.Szeto@Sun.COM 	 * i.e. if it's a data file, it assumes that the
13579585STim.Szeto@Sun.COM 	 * meta data is shared with the data.
13589585STim.Szeto@Sun.COM 	 */
13599585STim.Szeto@Sun.COM 	(void) strncpy(sbdLu->ilu_meta_fname, fname, metaFileNameLen);
13609585STim.Szeto@Sun.COM 
13619585STim.Szeto@Sun.COM 	sbdLu->ilu_struct_size = sizeof (sbd_import_lu_t) + iluBufSize - 8;
13629585STim.Szeto@Sun.COM 
13639585STim.Szeto@Sun.COM 	sbdIoctl.stmf_version = STMF_VERSION_1;
13649585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf_size = sbdLu->ilu_struct_size;
13659585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdLu;
13669585STim.Szeto@Sun.COM 	sbdIoctl.stmf_obuf_size = sbdLu->ilu_struct_size;
13679585STim.Szeto@Sun.COM 	sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdLu;
13689585STim.Szeto@Sun.COM 
13699585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, SBD_IOCTL_IMPORT_LU, &sbdIoctl);
13709585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
13719585STim.Szeto@Sun.COM 		savedErrno = errno;
13729585STim.Szeto@Sun.COM 		switch (savedErrno) {
13739585STim.Szeto@Sun.COM 			case EBUSY:
13749585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
13759585STim.Szeto@Sun.COM 				break;
13769585STim.Szeto@Sun.COM 			case EPERM:
13779585STim.Szeto@Sun.COM 			case EACCES:
13789585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
13799585STim.Szeto@Sun.COM 				break;
13809585STim.Szeto@Sun.COM 			default:
13819585STim.Szeto@Sun.COM 				diskError(sbdIoctl.stmf_error, &ret);
13829585STim.Szeto@Sun.COM 				if (ret == STMF_STATUS_ERROR) {
13839585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
13849585STim.Szeto@Sun.COM 					"importDiskLu:ioctl "
13859585STim.Szeto@Sun.COM 					"error(%d) (%d) (%d)", ioctlRet,
13869585STim.Szeto@Sun.COM 					    sbdIoctl.stmf_error, savedErrno);
13879585STim.Szeto@Sun.COM 				}
13889585STim.Szeto@Sun.COM 				break;
13899585STim.Szeto@Sun.COM 		}
13909585STim.Szeto@Sun.COM 	}
13919585STim.Szeto@Sun.COM 
13929585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
13939585STim.Szeto@Sun.COM 		goto done;
13949585STim.Szeto@Sun.COM 	}
13959585STim.Szeto@Sun.COM 
13969585STim.Szeto@Sun.COM 	/*
13979585STim.Szeto@Sun.COM 	 * on success, copy the resulting guid into the caller's guid if not
13989585STim.Szeto@Sun.COM 	 * NULL and add it to the persistent store for sbd
13999585STim.Szeto@Sun.COM 	 */
14009585STim.Szeto@Sun.COM 	if (createdGuid) {
14019585STim.Szeto@Sun.COM 		bcopy(sbdLu->ilu_ret_guid, createdGuid->guid,
14029585STim.Szeto@Sun.COM 		    sizeof (sbdLu->ilu_ret_guid));
14039585STim.Szeto@Sun.COM 		ret = addGuidToDiskStore(createdGuid, fname);
14049585STim.Szeto@Sun.COM 	} else {
14059585STim.Szeto@Sun.COM 		bcopy(sbdLu->ilu_ret_guid, iGuid.guid,
14069585STim.Szeto@Sun.COM 		    sizeof (sbdLu->ilu_ret_guid));
14079585STim.Szeto@Sun.COM 		ret = addGuidToDiskStore(&iGuid, fname);
14089585STim.Szeto@Sun.COM 	}
14099585STim.Szeto@Sun.COM done:
14109585STim.Szeto@Sun.COM 	free(sbdLu);
14119585STim.Szeto@Sun.COM 	(void) close(fd);
14129585STim.Szeto@Sun.COM 	return (ret);
14139585STim.Szeto@Sun.COM }
14149585STim.Szeto@Sun.COM 
14159585STim.Szeto@Sun.COM /*
14169585STim.Szeto@Sun.COM  * diskError
14179585STim.Szeto@Sun.COM  *
14189585STim.Szeto@Sun.COM  * Purpose: Translate sbd driver error
14199585STim.Szeto@Sun.COM  */
14209585STim.Szeto@Sun.COM static void
14219585STim.Szeto@Sun.COM diskError(uint32_t stmfError, int *ret)
14229585STim.Szeto@Sun.COM {
14239585STim.Szeto@Sun.COM 	switch (stmfError) {
14249585STim.Szeto@Sun.COM 		case SBD_RET_META_CREATION_FAILED:
14259585STim.Szeto@Sun.COM 		case SBD_RET_ZFS_META_CREATE_FAILED:
14269585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_META_CREATION;
14279585STim.Szeto@Sun.COM 			break;
14289585STim.Szeto@Sun.COM 		case SBD_RET_INVALID_BLKSIZE:
14299585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_INVALID_BLKSIZE;
14309585STim.Szeto@Sun.COM 			break;
14319585STim.Szeto@Sun.COM 		case SBD_RET_FILE_ALREADY_REGISTERED:
14329585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_FILE_IN_USE;
14339585STim.Szeto@Sun.COM 			break;
14349585STim.Szeto@Sun.COM 		case SBD_RET_GUID_ALREADY_REGISTERED:
14359585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_GUID_IN_USE;
14369585STim.Szeto@Sun.COM 			break;
14379585STim.Szeto@Sun.COM 		case SBD_RET_META_PATH_NOT_ABSOLUTE:
14389585STim.Szeto@Sun.COM 		case SBD_RET_META_FILE_LOOKUP_FAILED:
14399585STim.Szeto@Sun.COM 		case SBD_RET_META_FILE_OPEN_FAILED:
14409585STim.Szeto@Sun.COM 		case SBD_RET_META_FILE_GETATTR_FAILED:
14419585STim.Szeto@Sun.COM 		case SBD_RET_NO_META:
14429585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_META_FILE_NAME;
14439585STim.Szeto@Sun.COM 			break;
14449585STim.Szeto@Sun.COM 		case SBD_RET_DATA_PATH_NOT_ABSOLUTE:
14459585STim.Szeto@Sun.COM 		case SBD_RET_DATA_FILE_LOOKUP_FAILED:
14469585STim.Szeto@Sun.COM 		case SBD_RET_DATA_FILE_OPEN_FAILED:
14479585STim.Szeto@Sun.COM 		case SBD_RET_DATA_FILE_GETATTR_FAILED:
14489585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_DATA_FILE_NAME;
14499585STim.Szeto@Sun.COM 			break;
14509585STim.Szeto@Sun.COM 		case SBD_RET_FILE_SIZE_ERROR:
14519585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_FILE_SIZE_INVALID;
14529585STim.Szeto@Sun.COM 			break;
14539585STim.Szeto@Sun.COM 		case SBD_RET_SIZE_OUT_OF_RANGE:
14549585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_SIZE_OUT_OF_RANGE;
14559585STim.Szeto@Sun.COM 			break;
14569585STim.Szeto@Sun.COM 		case SBD_RET_LU_BUSY:
14579585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_LU_BUSY;
14589585STim.Szeto@Sun.COM 			break;
14599585STim.Szeto@Sun.COM 		case SBD_RET_WRITE_CACHE_SET_FAILED:
14609585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_WRITE_CACHE_SET;
14619585STim.Szeto@Sun.COM 			break;
14629585STim.Szeto@Sun.COM 		default:
14639585STim.Szeto@Sun.COM 			*ret = STMF_STATUS_ERROR;
14649585STim.Szeto@Sun.COM 			break;
14659585STim.Szeto@Sun.COM 	}
14669585STim.Szeto@Sun.COM }
14679585STim.Szeto@Sun.COM 
14689585STim.Szeto@Sun.COM /*
14699585STim.Szeto@Sun.COM  * Creates a logical unit resource of type STMF_DISK.
14709585STim.Szeto@Sun.COM  *
14719585STim.Szeto@Sun.COM  * No defaults should be set here as all defaults are derived from the
14729585STim.Szeto@Sun.COM  * driver's default settings.
14739585STim.Szeto@Sun.COM  */
14749585STim.Szeto@Sun.COM static int
14759585STim.Szeto@Sun.COM createDiskResource(luResourceImpl *hdl)
14769585STim.Szeto@Sun.COM {
14779585STim.Szeto@Sun.COM 	hdl->type = STMF_DISK;
14789585STim.Szeto@Sun.COM 
14799585STim.Szeto@Sun.COM 	hdl->resource = calloc(1, sizeof (diskResource));
14809585STim.Szeto@Sun.COM 	if (hdl->resource == NULL) {
14819585STim.Szeto@Sun.COM 		return (STMF_ERROR_NOMEM);
14829585STim.Szeto@Sun.COM 	}
14839585STim.Szeto@Sun.COM 
14849585STim.Szeto@Sun.COM 	return (STMF_STATUS_SUCCESS);
14859585STim.Szeto@Sun.COM }
14869585STim.Szeto@Sun.COM 
14879585STim.Szeto@Sun.COM /*
14889585STim.Szeto@Sun.COM  * stmfDeleteLu
14899585STim.Szeto@Sun.COM  *
14909585STim.Szeto@Sun.COM  * Purpose: Delete a logical unit
14919585STim.Szeto@Sun.COM  *
14929585STim.Szeto@Sun.COM  * hdl - handle to logical unit resource created via stmfCreateLuResource
14939585STim.Szeto@Sun.COM  *
14949585STim.Szeto@Sun.COM  * luGuid - If non-NULL, on success, contains the guid of the created logical
14959585STim.Szeto@Sun.COM  *	    unit
14969585STim.Szeto@Sun.COM  */
14979585STim.Szeto@Sun.COM int
14989585STim.Szeto@Sun.COM stmfDeleteLu(stmfGuid *luGuid)
14999585STim.Szeto@Sun.COM {
15009585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
15019585STim.Szeto@Sun.COM 	stmfLogicalUnitProperties luProps;
15029585STim.Szeto@Sun.COM 
15039585STim.Szeto@Sun.COM 	if (luGuid == NULL) {
15049585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
15059585STim.Szeto@Sun.COM 	}
15069585STim.Szeto@Sun.COM 
15079585STim.Szeto@Sun.COM 	/* Check logical unit provider name to call correct dtype function */
15089585STim.Szeto@Sun.COM 	if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps))
15099585STim.Szeto@Sun.COM 	    != STMF_STATUS_SUCCESS) {
15109585STim.Szeto@Sun.COM 		return (ret);
15119585STim.Szeto@Sun.COM 	} else {
15129585STim.Szeto@Sun.COM 		if (strcmp(luProps.providerName, "sbd") == 0) {
15139585STim.Szeto@Sun.COM 			ret = deleteDiskLu(luGuid);
15149585STim.Szeto@Sun.COM 		} else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) {
15159585STim.Szeto@Sun.COM 			return (STMF_ERROR_NOT_FOUND);
15169585STim.Szeto@Sun.COM 		} else {
15179585STim.Szeto@Sun.COM 			return (STMF_ERROR_INVALID_ARG);
15189585STim.Szeto@Sun.COM 		}
15199585STim.Szeto@Sun.COM 	}
15209585STim.Szeto@Sun.COM 
15219585STim.Szeto@Sun.COM 	return (ret);
15229585STim.Szeto@Sun.COM }
15239585STim.Szeto@Sun.COM 
15249585STim.Szeto@Sun.COM static int
15259585STim.Szeto@Sun.COM deleteDiskLu(stmfGuid *luGuid)
15269585STim.Szeto@Sun.COM {
15279585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
15289585STim.Szeto@Sun.COM 	int fd;
15299585STim.Szeto@Sun.COM 	int savedErrno;
15309585STim.Szeto@Sun.COM 	int ioctlRet;
15319585STim.Szeto@Sun.COM 	sbd_delete_lu_t deleteLu = {0};
15329585STim.Szeto@Sun.COM 
15339585STim.Szeto@Sun.COM 	stmf_iocdata_t sbdIoctl = {0};
15349585STim.Szeto@Sun.COM 
15359585STim.Szeto@Sun.COM 	/*
15369585STim.Szeto@Sun.COM 	 * Open control node for sbd
15379585STim.Szeto@Sun.COM 	 */
15389585STim.Szeto@Sun.COM 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
15399585STim.Szeto@Sun.COM 		return (ret);
15409585STim.Szeto@Sun.COM 
15419585STim.Szeto@Sun.COM 	ret = removeGuidFromDiskStore(luGuid);
15429585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
15439585STim.Szeto@Sun.COM 		goto done;
15449585STim.Szeto@Sun.COM 	}
15459585STim.Szeto@Sun.COM 
15469585STim.Szeto@Sun.COM 	bcopy(luGuid, deleteLu.dlu_guid, sizeof (deleteLu.dlu_guid));
15479585STim.Szeto@Sun.COM 	deleteLu.dlu_by_guid = 1;
15489585STim.Szeto@Sun.COM 
15499585STim.Szeto@Sun.COM 	sbdIoctl.stmf_version = STMF_VERSION_1;
15509585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf_size = sizeof (deleteLu);
15519585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)&deleteLu;
15529585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, SBD_IOCTL_DELETE_LU, &sbdIoctl);
15539585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
15549585STim.Szeto@Sun.COM 		savedErrno = errno;
15559585STim.Szeto@Sun.COM 		switch (savedErrno) {
15569585STim.Szeto@Sun.COM 			case EBUSY:
15579585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
15589585STim.Szeto@Sun.COM 				break;
15599585STim.Szeto@Sun.COM 			case EPERM:
15609585STim.Szeto@Sun.COM 			case EACCES:
15619585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
15629585STim.Szeto@Sun.COM 				break;
15639585STim.Szeto@Sun.COM 			case ENOENT:
15649585STim.Szeto@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
15659585STim.Szeto@Sun.COM 				break;
15669585STim.Szeto@Sun.COM 			default:
15679585STim.Szeto@Sun.COM 				syslog(LOG_DEBUG,
15689585STim.Szeto@Sun.COM 				    "deleteDiskLu:ioctl error(%d) (%d) (%d)",
15699585STim.Szeto@Sun.COM 				    ioctlRet, sbdIoctl.stmf_error, savedErrno);
15709585STim.Szeto@Sun.COM 				ret = STMF_STATUS_ERROR;
15719585STim.Szeto@Sun.COM 				break;
15729585STim.Szeto@Sun.COM 		}
15739585STim.Szeto@Sun.COM 	}
15749585STim.Szeto@Sun.COM 
15759585STim.Szeto@Sun.COM done:
15769585STim.Szeto@Sun.COM 	(void) close(fd);
15779585STim.Szeto@Sun.COM 	return (ret);
15789585STim.Szeto@Sun.COM }
15799585STim.Szeto@Sun.COM 
15809585STim.Szeto@Sun.COM /*
15819585STim.Szeto@Sun.COM  * stmfModifyLu
15829585STim.Szeto@Sun.COM  *
15839585STim.Szeto@Sun.COM  * Purpose: Modify properties of a logical unit
15849585STim.Szeto@Sun.COM  *
15859585STim.Szeto@Sun.COM  * luGuid - guid of registered logical unit
15869585STim.Szeto@Sun.COM  * prop - property to modify
15879585STim.Szeto@Sun.COM  * propVal - property value to set
15889585STim.Szeto@Sun.COM  *
15899585STim.Szeto@Sun.COM  */
15909585STim.Szeto@Sun.COM int
15919585STim.Szeto@Sun.COM stmfModifyLu(stmfGuid *luGuid, uint32_t prop, const char *propVal)
15929585STim.Szeto@Sun.COM {
15939585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
15949585STim.Szeto@Sun.COM 	stmfLogicalUnitProperties luProps;
15959585STim.Szeto@Sun.COM 
15969585STim.Szeto@Sun.COM 	if (luGuid == NULL) {
15979585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
15989585STim.Szeto@Sun.COM 	}
15999585STim.Szeto@Sun.COM 
16009585STim.Szeto@Sun.COM 	/* Check logical unit provider name to call correct dtype function */
16019585STim.Szeto@Sun.COM 	if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps))
16029585STim.Szeto@Sun.COM 	    != STMF_STATUS_SUCCESS) {
16039585STim.Szeto@Sun.COM 		return (ret);
16049585STim.Szeto@Sun.COM 	} else {
16059585STim.Szeto@Sun.COM 		if (strcmp(luProps.providerName, "sbd") == 0) {
16069585STim.Szeto@Sun.COM 			ret = modifyDiskLuProp(luGuid, NULL, prop, propVal);
16079585STim.Szeto@Sun.COM 		} else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) {
16089585STim.Szeto@Sun.COM 			return (STMF_ERROR_NOT_FOUND);
16099585STim.Szeto@Sun.COM 		} else {
16109585STim.Szeto@Sun.COM 			return (STMF_ERROR_INVALID_ARG);
16119585STim.Szeto@Sun.COM 		}
16129585STim.Szeto@Sun.COM 	}
16139585STim.Szeto@Sun.COM 
16149585STim.Szeto@Sun.COM 	return (ret);
16159585STim.Szeto@Sun.COM }
16169585STim.Szeto@Sun.COM 
16179585STim.Szeto@Sun.COM /*
16189585STim.Szeto@Sun.COM  * stmfModifyLuByFname
16199585STim.Szeto@Sun.COM  *
16209585STim.Szeto@Sun.COM  * Purpose: Modify a device by filename. Device does not need to be registered.
16219585STim.Szeto@Sun.COM  *
16229585STim.Szeto@Sun.COM  * dType - type of device to modify
16239585STim.Szeto@Sun.COM  *         STMF_DISK
16249585STim.Szeto@Sun.COM  *
16259585STim.Szeto@Sun.COM  * fname - filename or meta filename
16269585STim.Szeto@Sun.COM  * prop - valid property identifier
16279585STim.Szeto@Sun.COM  * propVal - property value
16289585STim.Szeto@Sun.COM  *
16299585STim.Szeto@Sun.COM  */
16309585STim.Szeto@Sun.COM int
16319585STim.Szeto@Sun.COM stmfModifyLuByFname(uint16_t dType, const char *fname, uint32_t prop,
16329585STim.Szeto@Sun.COM     const char *propVal)
16339585STim.Szeto@Sun.COM {
16349585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
16359585STim.Szeto@Sun.COM 	if (fname == NULL) {
16369585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
16379585STim.Szeto@Sun.COM 	}
16389585STim.Szeto@Sun.COM 
16399585STim.Szeto@Sun.COM 	if (dType == STMF_DISK) {
16409585STim.Szeto@Sun.COM 		ret = modifyDiskLuProp(NULL, fname, prop, propVal);
16419585STim.Szeto@Sun.COM 	} else {
16429585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
16439585STim.Szeto@Sun.COM 	}
16449585STim.Szeto@Sun.COM 
16459585STim.Szeto@Sun.COM 	return (ret);
16469585STim.Szeto@Sun.COM }
16479585STim.Szeto@Sun.COM 
16489585STim.Szeto@Sun.COM static int
16499585STim.Szeto@Sun.COM modifyDiskLuProp(stmfGuid *luGuid, const char *fname, uint32_t prop,
16509585STim.Szeto@Sun.COM     const char *propVal)
16519585STim.Szeto@Sun.COM {
16529585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
16539585STim.Szeto@Sun.COM 	luResource hdl = NULL;
16549585STim.Szeto@Sun.COM 	luResourceImpl *luPropsHdl;
16559585STim.Szeto@Sun.COM 
16569585STim.Szeto@Sun.COM 	ret = stmfCreateLuResource(STMF_DISK, &hdl);
16579585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
16589585STim.Szeto@Sun.COM 		return (ret);
16599585STim.Szeto@Sun.COM 	}
16609585STim.Szeto@Sun.COM 	ret = validateModifyDiskProp(prop);
16619585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
16629585STim.Szeto@Sun.COM 		(void) stmfFreeLuResource(hdl);
16639585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_PROP);
16649585STim.Szeto@Sun.COM 	}
16659585STim.Szeto@Sun.COM 	ret = stmfSetLuProp(hdl, prop, propVal);
16669585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
16679585STim.Szeto@Sun.COM 		(void) stmfFreeLuResource(hdl);
16689585STim.Szeto@Sun.COM 		return (ret);
16699585STim.Szeto@Sun.COM 	}
16709585STim.Szeto@Sun.COM 	luPropsHdl = hdl;
16719585STim.Szeto@Sun.COM 	ret = modifyDiskLu((diskResource *)luPropsHdl->resource, luGuid, fname);
16729585STim.Szeto@Sun.COM 	(void) stmfFreeLuResource(hdl);
16739585STim.Szeto@Sun.COM 	return (ret);
16749585STim.Szeto@Sun.COM }
16759585STim.Szeto@Sun.COM 
16769585STim.Szeto@Sun.COM static int
16779585STim.Szeto@Sun.COM validateModifyDiskProp(uint32_t prop)
16789585STim.Szeto@Sun.COM {
16799585STim.Szeto@Sun.COM 	switch (prop) {
16809585STim.Szeto@Sun.COM 		case STMF_LU_PROP_ALIAS:
16819585STim.Szeto@Sun.COM 		case STMF_LU_PROP_SIZE:
168210113SNattuvetty.Bhavyan@Sun.COM 		case STMF_LU_PROP_MGMT_URL:
16839585STim.Szeto@Sun.COM 		case STMF_LU_PROP_WRITE_PROTECT:
16849585STim.Szeto@Sun.COM 		case STMF_LU_PROP_WRITE_CACHE_DISABLE:
16859585STim.Szeto@Sun.COM 			return (STMF_STATUS_SUCCESS);
16869585STim.Szeto@Sun.COM 			break;
16879585STim.Szeto@Sun.COM 		default:
16889585STim.Szeto@Sun.COM 			return (STMF_STATUS_ERROR);
16899585STim.Szeto@Sun.COM 			break;
16909585STim.Szeto@Sun.COM 	}
16919585STim.Szeto@Sun.COM }
16929585STim.Szeto@Sun.COM 
16939585STim.Szeto@Sun.COM static int
16949585STim.Szeto@Sun.COM modifyDiskLu(diskResource *disk, stmfGuid *luGuid, const char *fname)
16959585STim.Szeto@Sun.COM {
16969585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
16979585STim.Szeto@Sun.COM 	int luAliasLen = 0;
169810113SNattuvetty.Bhavyan@Sun.COM 	int luMgmtUrlLen = 0;
16999585STim.Szeto@Sun.COM 	int mluBufSize = 0;
17009585STim.Szeto@Sun.COM 	int bufOffset = 0;
17019585STim.Szeto@Sun.COM 	int fd = 0;
17029585STim.Szeto@Sun.COM 	int ioctlRet;
17039585STim.Szeto@Sun.COM 	int savedErrno;
17049585STim.Szeto@Sun.COM 	int fnameSize = 0;
17059585STim.Szeto@Sun.COM 	stmf_iocdata_t sbdIoctl = {0};
17069585STim.Szeto@Sun.COM 
17079585STim.Szeto@Sun.COM 	sbd_modify_lu_t *sbdLu = NULL;
17089585STim.Szeto@Sun.COM 
17099585STim.Szeto@Sun.COM 	if (luGuid == NULL && fname == NULL) {
17109585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
17119585STim.Szeto@Sun.COM 	}
17129585STim.Szeto@Sun.COM 
17139585STim.Szeto@Sun.COM 	if (fname) {
17149585STim.Szeto@Sun.COM 		fnameSize = strlen(fname) + 1;
17159585STim.Szeto@Sun.COM 		mluBufSize += fnameSize;
17169585STim.Szeto@Sun.COM 	}
17179585STim.Szeto@Sun.COM 
17189585STim.Szeto@Sun.COM 	/*
17199585STim.Szeto@Sun.COM 	 * Open control node for sbd
17209585STim.Szeto@Sun.COM 	 */
17219585STim.Szeto@Sun.COM 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
17229585STim.Szeto@Sun.COM 		return (ret);
17239585STim.Szeto@Sun.COM 
17249585STim.Szeto@Sun.COM 	if (disk->luAliasValid) {
17259585STim.Szeto@Sun.COM 		luAliasLen = strlen(disk->luAlias);
17269585STim.Szeto@Sun.COM 		mluBufSize += luAliasLen + 1;
17279585STim.Szeto@Sun.COM 	}
17289585STim.Szeto@Sun.COM 
172910113SNattuvetty.Bhavyan@Sun.COM 	if (disk->luMgmtUrlValid) {
173010113SNattuvetty.Bhavyan@Sun.COM 		luMgmtUrlLen = strlen(disk->luMgmtUrl);
173110113SNattuvetty.Bhavyan@Sun.COM 		mluBufSize += luMgmtUrlLen + 1;
173210113SNattuvetty.Bhavyan@Sun.COM 	}
173310113SNattuvetty.Bhavyan@Sun.COM 
17349585STim.Szeto@Sun.COM 	/*
17359585STim.Szeto@Sun.COM 	 * 8 is the size of the buffer set aside for
17369585STim.Szeto@Sun.COM 	 * concatenation of variable length fields
17379585STim.Szeto@Sun.COM 	 */
17389585STim.Szeto@Sun.COM 	sbdLu = (sbd_modify_lu_t *)calloc(1,
17399585STim.Szeto@Sun.COM 	    sizeof (sbd_modify_lu_t) + mluBufSize - 8 + fnameSize);
17409585STim.Szeto@Sun.COM 	if (sbdLu == NULL) {
17419585STim.Szeto@Sun.COM 		(void) close(fd);
17429585STim.Szeto@Sun.COM 		return (STMF_ERROR_NOMEM);
17439585STim.Szeto@Sun.COM 	}
17449585STim.Szeto@Sun.COM 
17459585STim.Szeto@Sun.COM 	sbdLu->mlu_struct_size = sizeof (sbd_modify_lu_t) +
17469585STim.Szeto@Sun.COM 	    mluBufSize - 8 + fnameSize;
17479585STim.Szeto@Sun.COM 
17489585STim.Szeto@Sun.COM 	if (disk->luAliasValid) {
17499585STim.Szeto@Sun.COM 		sbdLu->mlu_alias_valid = 1;
17509585STim.Szeto@Sun.COM 		sbdLu->mlu_alias_off = bufOffset;
17519585STim.Szeto@Sun.COM 		bcopy(disk->luAlias, &(sbdLu->mlu_buf[bufOffset]),
17529585STim.Szeto@Sun.COM 		    luAliasLen + 1);
17539585STim.Szeto@Sun.COM 		bufOffset += luAliasLen + 1;
17549585STim.Szeto@Sun.COM 	}
17559585STim.Szeto@Sun.COM 
175610113SNattuvetty.Bhavyan@Sun.COM 	if (disk->luMgmtUrlValid) {
175710113SNattuvetty.Bhavyan@Sun.COM 		sbdLu->mlu_mgmt_url_valid = 1;
175810113SNattuvetty.Bhavyan@Sun.COM 		sbdLu->mlu_mgmt_url_off = bufOffset;
175910113SNattuvetty.Bhavyan@Sun.COM 		bcopy(disk->luMgmtUrl, &(sbdLu->mlu_buf[bufOffset]),
176010113SNattuvetty.Bhavyan@Sun.COM 		    luMgmtUrlLen + 1);
176110113SNattuvetty.Bhavyan@Sun.COM 		bufOffset += luMgmtUrlLen + 1;
176210113SNattuvetty.Bhavyan@Sun.COM 	}
176310113SNattuvetty.Bhavyan@Sun.COM 
17649585STim.Szeto@Sun.COM 	if (disk->luSizeValid) {
17659585STim.Szeto@Sun.COM 		sbdLu->mlu_lu_size_valid = 1;
17669585STim.Szeto@Sun.COM 		sbdLu->mlu_lu_size = disk->luSize;
17679585STim.Szeto@Sun.COM 	}
17689585STim.Szeto@Sun.COM 
17699585STim.Szeto@Sun.COM 	if (disk->writeProtectEnableValid) {
17709585STim.Szeto@Sun.COM 		sbdLu->mlu_write_protected_valid = 1;
17719585STim.Szeto@Sun.COM 		if (disk->writeProtectEnable) {
17729585STim.Szeto@Sun.COM 			sbdLu->mlu_write_protected = 1;
17739585STim.Szeto@Sun.COM 		}
17749585STim.Szeto@Sun.COM 	}
17759585STim.Szeto@Sun.COM 
17769585STim.Szeto@Sun.COM 	if (disk->writebackCacheDisableValid) {
17779585STim.Szeto@Sun.COM 		sbdLu->mlu_writeback_cache_disable_valid = 1;
17789585STim.Szeto@Sun.COM 		if (disk->writebackCacheDisable) {
17799585STim.Szeto@Sun.COM 			sbdLu->mlu_writeback_cache_disable = 1;
17809585STim.Szeto@Sun.COM 		}
17819585STim.Szeto@Sun.COM 	}
17829585STim.Szeto@Sun.COM 
17839585STim.Szeto@Sun.COM 	if (luGuid) {
17849585STim.Szeto@Sun.COM 		bcopy(luGuid, sbdLu->mlu_input_guid, sizeof (stmfGuid));
17859585STim.Szeto@Sun.COM 		sbdLu->mlu_by_guid = 1;
17869585STim.Szeto@Sun.COM 	} else {
17879585STim.Szeto@Sun.COM 		sbdLu->mlu_fname_off = bufOffset;
17889585STim.Szeto@Sun.COM 		bcopy(fname, &(sbdLu->mlu_buf[bufOffset]), fnameSize + 1);
17899585STim.Szeto@Sun.COM 		sbdLu->mlu_by_fname = 1;
17909585STim.Szeto@Sun.COM 	}
17919585STim.Szeto@Sun.COM 
17929585STim.Szeto@Sun.COM 	sbdIoctl.stmf_version = STMF_VERSION_1;
17939585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf_size = sbdLu->mlu_struct_size;
17949585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdLu;
17959585STim.Szeto@Sun.COM 
17969585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, SBD_IOCTL_MODIFY_LU, &sbdIoctl);
17979585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
17989585STim.Szeto@Sun.COM 		savedErrno = errno;
17999585STim.Szeto@Sun.COM 		switch (savedErrno) {
18009585STim.Szeto@Sun.COM 			case EBUSY:
18019585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
18029585STim.Szeto@Sun.COM 				break;
18039585STim.Szeto@Sun.COM 			case EPERM:
18049585STim.Szeto@Sun.COM 			case EACCES:
18059585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
18069585STim.Szeto@Sun.COM 				break;
18079585STim.Szeto@Sun.COM 			default:
18089585STim.Szeto@Sun.COM 				diskError(sbdIoctl.stmf_error, &ret);
18099585STim.Szeto@Sun.COM 				if (ret == STMF_STATUS_ERROR) {
18109585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
18119585STim.Szeto@Sun.COM 					"modifyDiskLu:ioctl "
18129585STim.Szeto@Sun.COM 					"error(%d) (%d) (%d)", ioctlRet,
18139585STim.Szeto@Sun.COM 					    sbdIoctl.stmf_error, savedErrno);
18149585STim.Szeto@Sun.COM 				}
18159585STim.Szeto@Sun.COM 				break;
18169585STim.Szeto@Sun.COM 		}
18179585STim.Szeto@Sun.COM 	}
18189585STim.Szeto@Sun.COM 
18199585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
18209585STim.Szeto@Sun.COM 		goto done;
18219585STim.Szeto@Sun.COM 	}
18229585STim.Szeto@Sun.COM 
18239585STim.Szeto@Sun.COM done:
18249585STim.Szeto@Sun.COM 	free(sbdLu);
18259585STim.Szeto@Sun.COM 	(void) close(fd);
18269585STim.Szeto@Sun.COM 	return (ret);
18279585STim.Szeto@Sun.COM }
18289585STim.Szeto@Sun.COM 
18299585STim.Szeto@Sun.COM /*
18309585STim.Szeto@Sun.COM  * removeGuidFromDiskStore
18319585STim.Szeto@Sun.COM  *
18329585STim.Szeto@Sun.COM  * Purpose: delete a logical unit from the sbd provider data
18339585STim.Szeto@Sun.COM  */
18349585STim.Szeto@Sun.COM static int
18359585STim.Szeto@Sun.COM removeGuidFromDiskStore(stmfGuid *guid)
18369585STim.Szeto@Sun.COM {
18379585STim.Szeto@Sun.COM 	return (persistDiskGuid(guid, NULL, B_FALSE));
18389585STim.Szeto@Sun.COM }
18399585STim.Szeto@Sun.COM 
18409585STim.Szeto@Sun.COM 
18419585STim.Szeto@Sun.COM /*
18429585STim.Szeto@Sun.COM  * addGuidToDiskStore
18439585STim.Szeto@Sun.COM  *
18449585STim.Szeto@Sun.COM  * Purpose: add a logical unit to the sbd provider data
18459585STim.Szeto@Sun.COM  */
18469585STim.Szeto@Sun.COM static int
18479585STim.Szeto@Sun.COM addGuidToDiskStore(stmfGuid *guid, char *filename)
18489585STim.Szeto@Sun.COM {
18499585STim.Szeto@Sun.COM 	return (persistDiskGuid(guid, filename, B_TRUE));
18509585STim.Szeto@Sun.COM }
18519585STim.Szeto@Sun.COM 
18529585STim.Szeto@Sun.COM 
18539585STim.Szeto@Sun.COM /*
18549585STim.Szeto@Sun.COM  * persistDiskGuid
18559585STim.Szeto@Sun.COM  *
18569585STim.Szeto@Sun.COM  * Purpose: Persist or unpersist a guid for the sbd provider data
18579585STim.Szeto@Sun.COM  *
18589585STim.Szeto@Sun.COM  */
18599585STim.Szeto@Sun.COM static int
18609585STim.Szeto@Sun.COM persistDiskGuid(stmfGuid *guid, char *filename, boolean_t persist)
18619585STim.Szeto@Sun.COM {
18629585STim.Szeto@Sun.COM 	char	    guidAsciiBuf[LU_ASCII_GUID_SIZE + 1] = {0};
18639585STim.Szeto@Sun.COM 	nvlist_t    *nvl = NULL;
18649585STim.Szeto@Sun.COM 
18659585STim.Szeto@Sun.COM 	uint64_t    setToken;
18669585STim.Szeto@Sun.COM 	boolean_t   retryGetProviderData = B_FALSE;
18679585STim.Szeto@Sun.COM 	boolean_t   newData = B_FALSE;
18689585STim.Szeto@Sun.COM 	int	    ret = STMF_STATUS_SUCCESS;
18699585STim.Szeto@Sun.COM 	int	    retryCnt = 0;
18709585STim.Szeto@Sun.COM 	int	    stmfRet;
18719585STim.Szeto@Sun.COM 
18729585STim.Szeto@Sun.COM 	/* if we're persisting a guid, there must be a filename */
18739585STim.Szeto@Sun.COM 	if (persist && !filename) {
18749585STim.Szeto@Sun.COM 		return (1);
18759585STim.Szeto@Sun.COM 	}
18769585STim.Szeto@Sun.COM 
18779585STim.Szeto@Sun.COM 	/* guid is stored in lowercase ascii hex */
18789585STim.Szeto@Sun.COM 	(void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf),
18799585STim.Szeto@Sun.COM 	    "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
18809585STim.Szeto@Sun.COM 	    "%02x%02x%02x%02x%02x%02x",
18819585STim.Szeto@Sun.COM 	    guid->guid[0], guid->guid[1], guid->guid[2], guid->guid[3],
18829585STim.Szeto@Sun.COM 	    guid->guid[4], guid->guid[5], guid->guid[6], guid->guid[7],
18839585STim.Szeto@Sun.COM 	    guid->guid[8], guid->guid[9], guid->guid[10], guid->guid[11],
18849585STim.Szeto@Sun.COM 	    guid->guid[12], guid->guid[13], guid->guid[14], guid->guid[15]);
18859585STim.Szeto@Sun.COM 
18869585STim.Szeto@Sun.COM 
18879585STim.Szeto@Sun.COM 	do {
18889585STim.Szeto@Sun.COM 		retryGetProviderData = B_FALSE;
18899585STim.Szeto@Sun.COM 		stmfRet = stmfGetProviderDataProt("sbd", &nvl,
18909585STim.Szeto@Sun.COM 		    STMF_LU_PROVIDER_TYPE, &setToken);
18919585STim.Szeto@Sun.COM 		if (stmfRet != STMF_STATUS_SUCCESS) {
18929585STim.Szeto@Sun.COM 			if (persist && stmfRet == STMF_ERROR_NOT_FOUND) {
18939585STim.Szeto@Sun.COM 				ret = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0);
18949585STim.Szeto@Sun.COM 				if (ret != 0) {
18959585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
18969585STim.Szeto@Sun.COM 					    "unpersistGuid:nvlist_alloc(%d)",
18979585STim.Szeto@Sun.COM 					    ret);
18989585STim.Szeto@Sun.COM 					ret = STMF_STATUS_ERROR;
18999585STim.Szeto@Sun.COM 					goto done;
19009585STim.Szeto@Sun.COM 				}
19019585STim.Szeto@Sun.COM 				newData = B_TRUE;
19029585STim.Szeto@Sun.COM 			} else {
19039585STim.Szeto@Sun.COM 				ret = stmfRet;
19049585STim.Szeto@Sun.COM 				goto done;
19059585STim.Szeto@Sun.COM 			}
19069585STim.Szeto@Sun.COM 		}
19079585STim.Szeto@Sun.COM 		if (persist) {
19089585STim.Szeto@Sun.COM 			ret = nvlist_add_string(nvl, guidAsciiBuf, filename);
19099585STim.Szeto@Sun.COM 		} else {
19109585STim.Szeto@Sun.COM 			ret = nvlist_remove(nvl, guidAsciiBuf,
19119585STim.Szeto@Sun.COM 			    DATA_TYPE_STRING);
19129585STim.Szeto@Sun.COM 			if (ret == ENOENT) {
19139585STim.Szeto@Sun.COM 				ret = 0;
19149585STim.Szeto@Sun.COM 			}
19159585STim.Szeto@Sun.COM 		}
19169585STim.Szeto@Sun.COM 		if (ret == 0) {
19179585STim.Szeto@Sun.COM 			if (newData) {
19189585STim.Szeto@Sun.COM 				stmfRet = stmfSetProviderDataProt("sbd", nvl,
19199585STim.Szeto@Sun.COM 				    STMF_LU_PROVIDER_TYPE, NULL);
19209585STim.Szeto@Sun.COM 			} else {
19219585STim.Szeto@Sun.COM 				stmfRet = stmfSetProviderDataProt("sbd", nvl,
19229585STim.Szeto@Sun.COM 				    STMF_LU_PROVIDER_TYPE, &setToken);
19239585STim.Szeto@Sun.COM 			}
19249585STim.Szeto@Sun.COM 			if (stmfRet != STMF_STATUS_SUCCESS) {
19259585STim.Szeto@Sun.COM 				if (stmfRet == STMF_ERROR_BUSY) {
19269585STim.Szeto@Sun.COM 					/* get/set failed, try again */
19279585STim.Szeto@Sun.COM 					retryGetProviderData = B_TRUE;
19289585STim.Szeto@Sun.COM 					if (retryCnt++ > MAX_PROVIDER_RETRY) {
19299585STim.Szeto@Sun.COM 						ret = stmfRet;
19309585STim.Szeto@Sun.COM 						break;
19319585STim.Szeto@Sun.COM 					}
19329585STim.Szeto@Sun.COM 					continue;
19339585STim.Szeto@Sun.COM 				} else if (stmfRet ==
19349585STim.Szeto@Sun.COM 				    STMF_ERROR_PROV_DATA_STALE) {
19359585STim.Szeto@Sun.COM 					/* update failed, try again */
19369585STim.Szeto@Sun.COM 					nvlist_free(nvl);
19379585STim.Szeto@Sun.COM 					nvl = NULL;
19389585STim.Szeto@Sun.COM 					retryGetProviderData = B_TRUE;
19399585STim.Szeto@Sun.COM 					if (retryCnt++ > MAX_PROVIDER_RETRY) {
19409585STim.Szeto@Sun.COM 						ret = stmfRet;
19419585STim.Szeto@Sun.COM 						break;
19429585STim.Szeto@Sun.COM 					}
19439585STim.Szeto@Sun.COM 					continue;
19449585STim.Szeto@Sun.COM 				} else {
19459585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
19469585STim.Szeto@Sun.COM 					    "unpersistGuid:error(%x)", stmfRet);
19479585STim.Szeto@Sun.COM 					ret = stmfRet;
19489585STim.Szeto@Sun.COM 				}
19499585STim.Szeto@Sun.COM 				break;
19509585STim.Szeto@Sun.COM 			}
19519585STim.Szeto@Sun.COM 		} else {
19529585STim.Szeto@Sun.COM 			syslog(LOG_DEBUG,
19539585STim.Szeto@Sun.COM 			    "unpersistGuid:error nvlist_add/remove(%d)",
19549585STim.Szeto@Sun.COM 			    ret);
19559585STim.Szeto@Sun.COM 			ret = STMF_STATUS_ERROR;
19569585STim.Szeto@Sun.COM 		}
19579585STim.Szeto@Sun.COM 	} while (retryGetProviderData);
19589585STim.Szeto@Sun.COM 
19599585STim.Szeto@Sun.COM done:
19609585STim.Szeto@Sun.COM 	nvlist_free(nvl);
19619585STim.Szeto@Sun.COM 	return (ret);
19629585STim.Szeto@Sun.COM }
19639585STim.Szeto@Sun.COM 
19649585STim.Szeto@Sun.COM 
19659585STim.Szeto@Sun.COM /*
19669585STim.Szeto@Sun.COM  * stmfGetLuProp
19679585STim.Szeto@Sun.COM  *
19689585STim.Szeto@Sun.COM  * Purpose: Get current value for a resource property
19699585STim.Szeto@Sun.COM  *
19709585STim.Szeto@Sun.COM  * hdl - luResource from a previous call to stmfCreateLuResource
19719585STim.Szeto@Sun.COM  *
19729585STim.Szeto@Sun.COM  * resourceProp - a valid resource property type
19739585STim.Szeto@Sun.COM  *
19749585STim.Szeto@Sun.COM  * propVal - void pointer to a pointer of the value to be retrieved
19759585STim.Szeto@Sun.COM  */
19769585STim.Szeto@Sun.COM int
19779585STim.Szeto@Sun.COM stmfGetLuProp(luResource hdl, uint32_t prop, char *propVal, size_t *propLen)
19789585STim.Szeto@Sun.COM {
19799585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
19809585STim.Szeto@Sun.COM 	luResourceImpl *luPropsHdl = hdl;
19819585STim.Szeto@Sun.COM 	if (hdl == NULL || propLen == NULL || propVal == NULL) {
19829585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
19839585STim.Szeto@Sun.COM 	}
19849585STim.Szeto@Sun.COM 
19859585STim.Szeto@Sun.COM 	if (luPropsHdl->type == STMF_DISK) {
19869585STim.Szeto@Sun.COM 		ret = getDiskProp(luPropsHdl, prop, propVal, propLen);
19879585STim.Szeto@Sun.COM 	} else {
19889585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
19899585STim.Szeto@Sun.COM 	}
19909585STim.Szeto@Sun.COM 
19919585STim.Szeto@Sun.COM 	return (ret);
19929585STim.Szeto@Sun.COM }
19939585STim.Szeto@Sun.COM 
19949585STim.Szeto@Sun.COM /*
19959585STim.Szeto@Sun.COM  * stmfGetLuResource
19969585STim.Szeto@Sun.COM  *
19979585STim.Szeto@Sun.COM  * Purpose: Get a logical unit resource handle for a given logical unit.
19989585STim.Szeto@Sun.COM  *
19999585STim.Szeto@Sun.COM  * hdl - pointer to luResource
20009585STim.Szeto@Sun.COM  */
20019585STim.Szeto@Sun.COM int
20029585STim.Szeto@Sun.COM stmfGetLuResource(stmfGuid *luGuid, luResource *hdl)
20039585STim.Szeto@Sun.COM {
20049585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
20059585STim.Szeto@Sun.COM 	stmfLogicalUnitProperties luProps;
20069585STim.Szeto@Sun.COM 
20079585STim.Szeto@Sun.COM 
20089585STim.Szeto@Sun.COM 	/* Check logical unit provider name to call correct dtype function */
20099585STim.Szeto@Sun.COM 	if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps))
20109585STim.Szeto@Sun.COM 	    != STMF_STATUS_SUCCESS) {
20119585STim.Szeto@Sun.COM 		return (ret);
20129585STim.Szeto@Sun.COM 	} else {
20139585STim.Szeto@Sun.COM 		if (strcmp(luProps.providerName, "sbd") == 0) {
20149585STim.Szeto@Sun.COM 			ret = getDiskAllProps(luGuid, hdl);
20159585STim.Szeto@Sun.COM 		} else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) {
20169585STim.Szeto@Sun.COM 			return (STMF_ERROR_NOT_FOUND);
20179585STim.Szeto@Sun.COM 		} else {
20189585STim.Szeto@Sun.COM 			return (STMF_ERROR_INVALID_ARG);
20199585STim.Szeto@Sun.COM 		}
20209585STim.Szeto@Sun.COM 	}
20219585STim.Szeto@Sun.COM 
20229585STim.Szeto@Sun.COM 	return (ret);
20239585STim.Szeto@Sun.COM }
20249585STim.Szeto@Sun.COM 
20259585STim.Szeto@Sun.COM /*
20269585STim.Szeto@Sun.COM  * getDiskAllProps
20279585STim.Szeto@Sun.COM  *
20289585STim.Szeto@Sun.COM  * Purpose: load all disk properties from sbd driver
20299585STim.Szeto@Sun.COM  *
20309585STim.Szeto@Sun.COM  * luGuid - guid of disk device for which properties are to be retrieved
20319585STim.Szeto@Sun.COM  * hdl - allocated luResource into which properties are to be copied
20329585STim.Szeto@Sun.COM  *
20339585STim.Szeto@Sun.COM  */
20349585STim.Szeto@Sun.COM static int
20359585STim.Szeto@Sun.COM getDiskAllProps(stmfGuid *luGuid, luResource *hdl)
20369585STim.Szeto@Sun.COM {
20379585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
20389585STim.Szeto@Sun.COM 	int fd;
20399585STim.Szeto@Sun.COM 	sbd_lu_props_t *sbdProps;
20409585STim.Szeto@Sun.COM 	int ioctlRet;
20419585STim.Szeto@Sun.COM 	int savedErrno;
20429585STim.Szeto@Sun.COM 	int sbdPropsSize = sizeof (*sbdProps) + MAX_SBD_PROPS;
20439585STim.Szeto@Sun.COM 	stmf_iocdata_t sbdIoctl = {0};
20449585STim.Szeto@Sun.COM 
20459585STim.Szeto@Sun.COM 	/*
20469585STim.Szeto@Sun.COM 	 * Open control node for sbd
20479585STim.Szeto@Sun.COM 	 */
20489585STim.Szeto@Sun.COM 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
20499585STim.Szeto@Sun.COM 		return (ret);
20509585STim.Szeto@Sun.COM 
20519585STim.Szeto@Sun.COM 
20529585STim.Szeto@Sun.COM 	*hdl = calloc(1, sizeof (luResourceImpl));
20539585STim.Szeto@Sun.COM 	if (*hdl == NULL) {
20549585STim.Szeto@Sun.COM 		(void) close(fd);
20559585STim.Szeto@Sun.COM 		return (STMF_ERROR_NOMEM);
20569585STim.Szeto@Sun.COM 	}
20579585STim.Szeto@Sun.COM 
20589585STim.Szeto@Sun.COM 	sbdProps = calloc(1, sbdPropsSize);
20599585STim.Szeto@Sun.COM 	if (sbdProps == NULL) {
20609585STim.Szeto@Sun.COM 		free(*hdl);
20619585STim.Szeto@Sun.COM 		(void) close(fd);
20629585STim.Szeto@Sun.COM 		return (STMF_ERROR_NOMEM);
20639585STim.Szeto@Sun.COM 	}
20649585STim.Szeto@Sun.COM 
20659585STim.Szeto@Sun.COM 	ret = createDiskResource((luResourceImpl *)*hdl);
20669585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
20679585STim.Szeto@Sun.COM 		free(*hdl);
20689585STim.Szeto@Sun.COM 		(void) close(fd);
20699585STim.Szeto@Sun.COM 		return (ret);
20709585STim.Szeto@Sun.COM 	}
20719585STim.Szeto@Sun.COM 
20729585STim.Szeto@Sun.COM 	sbdProps->slp_input_guid = 1;
20739585STim.Szeto@Sun.COM 	bcopy(luGuid, sbdProps->slp_guid, sizeof (sbdProps->slp_guid));
20749585STim.Szeto@Sun.COM 
20759585STim.Szeto@Sun.COM 	sbdIoctl.stmf_version = STMF_VERSION_1;
20769585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf_size = sbdPropsSize;
20779585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdProps;
20789585STim.Szeto@Sun.COM 	sbdIoctl.stmf_obuf_size = sbdPropsSize;
20799585STim.Szeto@Sun.COM 	sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdProps;
20809585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, SBD_IOCTL_GET_LU_PROPS, &sbdIoctl);
20819585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
20829585STim.Szeto@Sun.COM 		savedErrno = errno;
20839585STim.Szeto@Sun.COM 		switch (savedErrno) {
20849585STim.Szeto@Sun.COM 			case EBUSY:
20859585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
20869585STim.Szeto@Sun.COM 				break;
20879585STim.Szeto@Sun.COM 			case EPERM:
20889585STim.Szeto@Sun.COM 			case EACCES:
20899585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
20909585STim.Szeto@Sun.COM 				break;
20919585STim.Szeto@Sun.COM 			case ENOENT:
20929585STim.Szeto@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
20939585STim.Szeto@Sun.COM 				break;
20949585STim.Szeto@Sun.COM 			default:
20959585STim.Szeto@Sun.COM 				syslog(LOG_DEBUG,
20969585STim.Szeto@Sun.COM 				    "getDiskAllProps:ioctl error(%d) (%d) (%d)",
20979585STim.Szeto@Sun.COM 				    ioctlRet, sbdIoctl.stmf_error, savedErrno);
20989585STim.Szeto@Sun.COM 				ret = STMF_STATUS_ERROR;
20999585STim.Szeto@Sun.COM 				break;
21009585STim.Szeto@Sun.COM 		}
21019585STim.Szeto@Sun.COM 	}
21029585STim.Szeto@Sun.COM 
21039585STim.Szeto@Sun.COM 	if (ret == STMF_STATUS_SUCCESS) {
21049585STim.Szeto@Sun.COM 		ret = loadDiskPropsFromDriver((luResourceImpl *)*hdl, sbdProps);
21059585STim.Szeto@Sun.COM 	}
21069585STim.Szeto@Sun.COM 
21079585STim.Szeto@Sun.COM 	(void) close(fd);
21089585STim.Szeto@Sun.COM 	return (ret);
21099585STim.Szeto@Sun.COM }
21109585STim.Szeto@Sun.COM 
21119585STim.Szeto@Sun.COM /*
21129585STim.Szeto@Sun.COM  * loadDiskPropsFromDriver
21139585STim.Szeto@Sun.COM  *
21149585STim.Szeto@Sun.COM  * Purpose: Retrieve all disk type properties from sbd driver
21159585STim.Szeto@Sun.COM  *
21169585STim.Szeto@Sun.COM  * hdl - Allocated luResourceImpl
21179585STim.Szeto@Sun.COM  * sbdProps - sbd_lu_props_t structure returned from sbd driver
21189585STim.Szeto@Sun.COM  *
21199585STim.Szeto@Sun.COM  */
21209585STim.Szeto@Sun.COM static int
21219585STim.Szeto@Sun.COM loadDiskPropsFromDriver(luResourceImpl *hdl, sbd_lu_props_t *sbdProps)
21229585STim.Szeto@Sun.COM {
21239585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
21249585STim.Szeto@Sun.COM 	diskResource *diskLu = hdl->resource;
21259585STim.Szeto@Sun.COM 	/* copy guid */
21269585STim.Szeto@Sun.COM 	diskLu->luGuidValid = B_TRUE;
21279585STim.Szeto@Sun.COM 	bcopy(sbdProps->slp_guid, diskLu->luGuid, sizeof (sbdProps->slp_guid));
21289585STim.Szeto@Sun.COM 
21299585STim.Szeto@Sun.COM 	if (sbdProps->slp_separate_meta && sbdProps->slp_meta_fname_valid) {
21309585STim.Szeto@Sun.COM 		diskLu->luMetaFileNameValid = B_TRUE;
21319585STim.Szeto@Sun.COM 		if (strlcpy(diskLu->luMetaFileName,
21329585STim.Szeto@Sun.COM 		    (char *)&(sbdProps->slp_buf[sbdProps->slp_meta_fname_off]),
21339585STim.Szeto@Sun.COM 		    sizeof (diskLu->luMetaFileName)) >=
21349585STim.Szeto@Sun.COM 		    sizeof (diskLu->luMetaFileName)) {
21359585STim.Szeto@Sun.COM 			return (STMF_STATUS_ERROR);
21369585STim.Szeto@Sun.COM 		}
21379585STim.Szeto@Sun.COM 	}
21389585STim.Szeto@Sun.COM 
21399585STim.Szeto@Sun.COM 	if (sbdProps->slp_data_fname_valid) {
21409585STim.Szeto@Sun.COM 		diskLu->luDataFileNameValid = B_TRUE;
21419585STim.Szeto@Sun.COM 		if (strlcpy(diskLu->luDataFileName,
21429585STim.Szeto@Sun.COM 		    (char *)&(sbdProps->slp_buf[sbdProps->slp_data_fname_off]),
21439585STim.Szeto@Sun.COM 		    sizeof (diskLu->luDataFileName)) >=
21449585STim.Szeto@Sun.COM 		    sizeof (diskLu->luDataFileName)) {
21459585STim.Szeto@Sun.COM 			return (STMF_STATUS_ERROR);
21469585STim.Szeto@Sun.COM 		}
21479585STim.Szeto@Sun.COM 	}
21489585STim.Szeto@Sun.COM 
21499585STim.Szeto@Sun.COM 	if (sbdProps->slp_serial_valid) {
21509585STim.Szeto@Sun.COM 		diskLu->serialNumValid = B_TRUE;
21519585STim.Szeto@Sun.COM 		bcopy(&(sbdProps->slp_buf[sbdProps->slp_serial_off]),
21529585STim.Szeto@Sun.COM 		    diskLu->serialNum, sbdProps->slp_serial_size);
21539585STim.Szeto@Sun.COM 	}
21549585STim.Szeto@Sun.COM 
215510113SNattuvetty.Bhavyan@Sun.COM 	if (sbdProps->slp_mgmt_url_valid) {
215610113SNattuvetty.Bhavyan@Sun.COM 		diskLu->luMgmtUrlValid = B_TRUE;
215710113SNattuvetty.Bhavyan@Sun.COM 		if (strlcpy(diskLu->luMgmtUrl,
215810113SNattuvetty.Bhavyan@Sun.COM 		    (char *)&(sbdProps->slp_buf[sbdProps->slp_mgmt_url_off]),
215910113SNattuvetty.Bhavyan@Sun.COM 		    sizeof (diskLu->luMgmtUrl)) >=
216010113SNattuvetty.Bhavyan@Sun.COM 		    sizeof (diskLu->luMgmtUrl)) {
216110113SNattuvetty.Bhavyan@Sun.COM 			return (STMF_STATUS_ERROR);
216210113SNattuvetty.Bhavyan@Sun.COM 		}
216310113SNattuvetty.Bhavyan@Sun.COM 	}
216410113SNattuvetty.Bhavyan@Sun.COM 
21659585STim.Szeto@Sun.COM 	if (sbdProps->slp_alias_valid) {
21669585STim.Szeto@Sun.COM 		diskLu->luAliasValid = B_TRUE;
21679585STim.Szeto@Sun.COM 		if (strlcpy(diskLu->luAlias,
21689585STim.Szeto@Sun.COM 		    (char *)&(sbdProps->slp_buf[sbdProps->slp_alias_off]),
21699585STim.Szeto@Sun.COM 		    sizeof (diskLu->luAlias)) >=
21709585STim.Szeto@Sun.COM 		    sizeof (diskLu->luAlias)) {
21719585STim.Szeto@Sun.COM 			return (STMF_STATUS_ERROR);
21729585STim.Szeto@Sun.COM 		}
21739585STim.Szeto@Sun.COM 	} else { /* set alias to data filename if not set */
21749585STim.Szeto@Sun.COM 		if (sbdProps->slp_data_fname_valid) {
21759585STim.Szeto@Sun.COM 			diskLu->luAliasValid = B_TRUE;
21769585STim.Szeto@Sun.COM 			if (strlcpy(diskLu->luAlias,
21779585STim.Szeto@Sun.COM 			    (char *)&(sbdProps->slp_buf[
21789585STim.Szeto@Sun.COM 			    sbdProps->slp_data_fname_off]),
21799585STim.Szeto@Sun.COM 			    sizeof (diskLu->luAlias)) >=
21809585STim.Szeto@Sun.COM 			    sizeof (diskLu->luAlias)) {
21819585STim.Szeto@Sun.COM 				return (STMF_STATUS_ERROR);
21829585STim.Szeto@Sun.COM 			}
21839585STim.Szeto@Sun.COM 		}
21849585STim.Szeto@Sun.COM 	}
21859585STim.Szeto@Sun.COM 
21869585STim.Szeto@Sun.COM 	diskLu->vidValid = B_TRUE;
21879585STim.Szeto@Sun.COM 	bcopy(sbdProps->slp_vid, diskLu->vid, sizeof (diskLu->vid));
21889585STim.Szeto@Sun.COM 
21899585STim.Szeto@Sun.COM 	diskLu->pidValid = B_TRUE;
21909585STim.Szeto@Sun.COM 	bcopy(sbdProps->slp_pid, diskLu->pid, sizeof (diskLu->pid));
21919585STim.Szeto@Sun.COM 
21929585STim.Szeto@Sun.COM 	diskLu->revValid = B_TRUE;
21939585STim.Szeto@Sun.COM 	bcopy(sbdProps->slp_rev, diskLu->rev, sizeof (diskLu->rev));
21949585STim.Szeto@Sun.COM 
21959585STim.Szeto@Sun.COM 	diskLu->writeProtectEnableValid = B_TRUE;
21969585STim.Szeto@Sun.COM 	if (sbdProps->slp_write_protected) {
21979585STim.Szeto@Sun.COM 		diskLu->writeProtectEnable = B_TRUE;
21989585STim.Szeto@Sun.COM 	}
21999585STim.Szeto@Sun.COM 
22009585STim.Szeto@Sun.COM 	diskLu->writebackCacheDisableValid = B_TRUE;
22019585STim.Szeto@Sun.COM 	if (sbdProps->slp_writeback_cache_disable_cur) {
22029585STim.Szeto@Sun.COM 		diskLu->writebackCacheDisable = B_TRUE;
22039585STim.Szeto@Sun.COM 	}
22049585STim.Szeto@Sun.COM 
22059585STim.Szeto@Sun.COM 	diskLu->blkSizeValid = B_TRUE;
22069585STim.Szeto@Sun.COM 	diskLu->blkSize = sbdProps->slp_blksize;
22079585STim.Szeto@Sun.COM 
22089585STim.Szeto@Sun.COM 	diskLu->luSizeValid = B_TRUE;
22099585STim.Szeto@Sun.COM 	diskLu->luSize = sbdProps->slp_lu_size;
22109585STim.Szeto@Sun.COM 
22119585STim.Szeto@Sun.COM 	return (ret);
22129585STim.Szeto@Sun.COM }
22139585STim.Szeto@Sun.COM 
22149585STim.Szeto@Sun.COM 
22159585STim.Szeto@Sun.COM /*
22169585STim.Szeto@Sun.COM  * stmfSetLuProp
22179585STim.Szeto@Sun.COM  *
22189585STim.Szeto@Sun.COM  * Purpose: set a property on an luResource
22199585STim.Szeto@Sun.COM  *
22209585STim.Szeto@Sun.COM  * hdl - allocated luResource
22219585STim.Szeto@Sun.COM  * prop - property identifier
22229585STim.Szeto@Sun.COM  * propVal - property value to be set
22239585STim.Szeto@Sun.COM  */
22249585STim.Szeto@Sun.COM int
22259585STim.Szeto@Sun.COM stmfSetLuProp(luResource hdl, uint32_t prop, const char *propVal)
22269585STim.Szeto@Sun.COM {
22279585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
22289585STim.Szeto@Sun.COM 	luResourceImpl *luPropsHdl = hdl;
22299585STim.Szeto@Sun.COM 	if (hdl == NULL) {
22309585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
22319585STim.Szeto@Sun.COM 	}
22329585STim.Szeto@Sun.COM 
22339585STim.Szeto@Sun.COM 	if (luPropsHdl->type == STMF_DISK) {
22349585STim.Szeto@Sun.COM 		ret = setDiskProp(luPropsHdl, prop, propVal);
22359585STim.Szeto@Sun.COM 	} else {
22369585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
22379585STim.Szeto@Sun.COM 	}
22389585STim.Szeto@Sun.COM 
22399585STim.Szeto@Sun.COM 	return (ret);
22409585STim.Szeto@Sun.COM }
22419585STim.Szeto@Sun.COM 
22429585STim.Szeto@Sun.COM /*
22439585STim.Szeto@Sun.COM  * getDiskProp
22449585STim.Szeto@Sun.COM  *
22459585STim.Szeto@Sun.COM  * Purpose: retrieve a given property from a logical unit resource of type disk
22469585STim.Szeto@Sun.COM  *
22479585STim.Szeto@Sun.COM  * hdl - allocated luResourceImpl
22489585STim.Szeto@Sun.COM  * prop - property identifier
22499585STim.Szeto@Sun.COM  * propVal - pointer to character to contain the retrieved property value
22509585STim.Szeto@Sun.COM  * propLen - On input this is the length of propVal. On failure, it contains the
22519585STim.Szeto@Sun.COM  *           number of bytes required for propVal
22529585STim.Szeto@Sun.COM  */
22539585STim.Szeto@Sun.COM static int
22549585STim.Szeto@Sun.COM getDiskProp(luResourceImpl *hdl, uint32_t prop, char *propVal, size_t *propLen)
22559585STim.Szeto@Sun.COM {
22569585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
22579585STim.Szeto@Sun.COM 	diskResource *diskLu = hdl->resource;
22589585STim.Szeto@Sun.COM 	size_t reqLen;
22599585STim.Szeto@Sun.COM 
22609585STim.Szeto@Sun.COM 	switch (prop) {
22619585STim.Szeto@Sun.COM 		case STMF_LU_PROP_BLOCK_SIZE:
22629585STim.Szeto@Sun.COM 			if (diskLu->blkSizeValid == B_FALSE) {
22639585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
22649585STim.Szeto@Sun.COM 			}
22659585STim.Szeto@Sun.COM 			reqLen = snprintf(propVal, *propLen, "%llu",
22669585STim.Szeto@Sun.COM 			    (u_longlong_t)diskLu->blkSize);
22679585STim.Szeto@Sun.COM 			if (reqLen >= *propLen) {
22689585STim.Szeto@Sun.COM 				*propLen = reqLen + 1;
22699585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
22709585STim.Szeto@Sun.COM 			}
22719585STim.Szeto@Sun.COM 			break;
22729585STim.Szeto@Sun.COM 		case STMF_LU_PROP_FILENAME:
22739585STim.Szeto@Sun.COM 			if (diskLu->luDataFileNameValid == B_FALSE) {
22749585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
22759585STim.Szeto@Sun.COM 			}
22769585STim.Szeto@Sun.COM 			if ((reqLen = strlcpy(propVal, diskLu->luDataFileName,
22779585STim.Szeto@Sun.COM 			    *propLen)) >= *propLen) {
22789585STim.Szeto@Sun.COM 				*propLen = reqLen + 1;
22799585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
22809585STim.Szeto@Sun.COM 			}
22819585STim.Szeto@Sun.COM 			break;
22829585STim.Szeto@Sun.COM 		case STMF_LU_PROP_META_FILENAME:
22839585STim.Szeto@Sun.COM 			if (diskLu->luMetaFileNameValid == B_FALSE) {
22849585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
22859585STim.Szeto@Sun.COM 			}
22869585STim.Szeto@Sun.COM 			if ((reqLen = strlcpy(propVal, diskLu->luMetaFileName,
22879585STim.Szeto@Sun.COM 			    *propLen)) >= *propLen) {
22889585STim.Szeto@Sun.COM 				*propLen = reqLen + 1;
22899585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
22909585STim.Szeto@Sun.COM 			}
22919585STim.Szeto@Sun.COM 			break;
229210113SNattuvetty.Bhavyan@Sun.COM 		case STMF_LU_PROP_MGMT_URL:
229310113SNattuvetty.Bhavyan@Sun.COM 			if (diskLu->luMgmtUrlValid == B_FALSE) {
229410113SNattuvetty.Bhavyan@Sun.COM 				return (STMF_ERROR_NO_PROP);
229510113SNattuvetty.Bhavyan@Sun.COM 			}
229610113SNattuvetty.Bhavyan@Sun.COM 			if ((reqLen = strlcpy(propVal, diskLu->luMgmtUrl,
229710113SNattuvetty.Bhavyan@Sun.COM 			    *propLen)) >= *propLen) {
229810113SNattuvetty.Bhavyan@Sun.COM 				*propLen = reqLen + 1;
229910113SNattuvetty.Bhavyan@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
230010113SNattuvetty.Bhavyan@Sun.COM 			}
230110113SNattuvetty.Bhavyan@Sun.COM 			break;
23029585STim.Szeto@Sun.COM 		case STMF_LU_PROP_GUID:
23039585STim.Szeto@Sun.COM 			if (diskLu->luGuidValid == B_FALSE) {
23049585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
23059585STim.Szeto@Sun.COM 			}
23069585STim.Szeto@Sun.COM 			reqLen = snprintf(propVal, *propLen,
23079585STim.Szeto@Sun.COM 			    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X"
23089585STim.Szeto@Sun.COM 			    "%02X%02X%02X%02X",
23099585STim.Szeto@Sun.COM 			    diskLu->luGuid[0], diskLu->luGuid[1],
23109585STim.Szeto@Sun.COM 			    diskLu->luGuid[2], diskLu->luGuid[3],
23119585STim.Szeto@Sun.COM 			    diskLu->luGuid[4], diskLu->luGuid[5],
23129585STim.Szeto@Sun.COM 			    diskLu->luGuid[6], diskLu->luGuid[7],
23139585STim.Szeto@Sun.COM 			    diskLu->luGuid[8], diskLu->luGuid[9],
23149585STim.Szeto@Sun.COM 			    diskLu->luGuid[10], diskLu->luGuid[11],
23159585STim.Szeto@Sun.COM 			    diskLu->luGuid[12], diskLu->luGuid[13],
23169585STim.Szeto@Sun.COM 			    diskLu->luGuid[14], diskLu->luGuid[15]);
23179585STim.Szeto@Sun.COM 			if (reqLen >= *propLen) {
23189585STim.Szeto@Sun.COM 				*propLen = reqLen + 1;
23199585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
23209585STim.Szeto@Sun.COM 			}
23219585STim.Szeto@Sun.COM 			break;
23229585STim.Szeto@Sun.COM 		case STMF_LU_PROP_SERIAL_NUM:
23239585STim.Szeto@Sun.COM 			if (diskLu->serialNumValid == B_FALSE) {
23249585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
23259585STim.Szeto@Sun.COM 			}
23269585STim.Szeto@Sun.COM 			if ((reqLen = strlcpy(propVal, diskLu->serialNum,
23279585STim.Szeto@Sun.COM 			    *propLen)) >= *propLen) {
23289585STim.Szeto@Sun.COM 				*propLen = reqLen + 1;
23299585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
23309585STim.Szeto@Sun.COM 			}
23319585STim.Szeto@Sun.COM 			break;
23329585STim.Szeto@Sun.COM 		case STMF_LU_PROP_SIZE:
23339585STim.Szeto@Sun.COM 			if (diskLu->luSizeValid == B_FALSE) {
23349585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
23359585STim.Szeto@Sun.COM 			}
23369585STim.Szeto@Sun.COM 			(void) snprintf(propVal, *propLen, "%llu",
23379585STim.Szeto@Sun.COM 			    (u_longlong_t)diskLu->luSize);
23389585STim.Szeto@Sun.COM 			break;
23399585STim.Szeto@Sun.COM 		case STMF_LU_PROP_ALIAS:
23409585STim.Szeto@Sun.COM 			if (diskLu->luAliasValid == B_FALSE) {
23419585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
23429585STim.Szeto@Sun.COM 			}
23439585STim.Szeto@Sun.COM 			if ((reqLen = strlcpy(propVal, diskLu->luAlias,
23449585STim.Szeto@Sun.COM 			    *propLen)) >= *propLen) {
23459585STim.Szeto@Sun.COM 				*propLen = reqLen + 1;
23469585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
23479585STim.Szeto@Sun.COM 			}
23489585STim.Szeto@Sun.COM 			break;
23499585STim.Szeto@Sun.COM 		case STMF_LU_PROP_VID:
23509585STim.Szeto@Sun.COM 			if (diskLu->vidValid == B_FALSE) {
23519585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
23529585STim.Szeto@Sun.COM 			}
23539585STim.Szeto@Sun.COM 			if (*propLen <= sizeof (diskLu->vid)) {
23549585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
23559585STim.Szeto@Sun.COM 			}
23569585STim.Szeto@Sun.COM 			bcopy(diskLu->vid, propVal, sizeof (diskLu->vid));
23579585STim.Szeto@Sun.COM 			propVal[sizeof (diskLu->vid)] = 0;
23589585STim.Szeto@Sun.COM 			break;
23599585STim.Szeto@Sun.COM 		case STMF_LU_PROP_PID:
23609585STim.Szeto@Sun.COM 			if (diskLu->pidValid == B_FALSE) {
23619585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
23629585STim.Szeto@Sun.COM 			}
23639585STim.Szeto@Sun.COM 			if (*propLen <= sizeof (diskLu->pid)) {
23649585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
23659585STim.Szeto@Sun.COM 			}
23669585STim.Szeto@Sun.COM 			bcopy(diskLu->pid, propVal, sizeof (diskLu->pid));
23679585STim.Szeto@Sun.COM 			propVal[sizeof (diskLu->pid)] = 0;
23689585STim.Szeto@Sun.COM 			break;
23699585STim.Szeto@Sun.COM 		case STMF_LU_PROP_WRITE_PROTECT:
23709585STim.Szeto@Sun.COM 			if (diskLu->writeProtectEnableValid == B_FALSE) {
23719585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
23729585STim.Szeto@Sun.COM 			}
23739585STim.Szeto@Sun.COM 			if (diskLu->writeProtectEnable) {
23749585STim.Szeto@Sun.COM 				if ((reqLen = strlcpy(propVal, "true",
23759585STim.Szeto@Sun.COM 				    *propLen)) >= *propLen) {
23769585STim.Szeto@Sun.COM 					*propLen = reqLen + 1;
23779585STim.Szeto@Sun.COM 					return (STMF_ERROR_INVALID_ARG);
23789585STim.Szeto@Sun.COM 				}
23799585STim.Szeto@Sun.COM 			} else {
23809585STim.Szeto@Sun.COM 				if ((reqLen = strlcpy(propVal, "false",
23819585STim.Szeto@Sun.COM 				    *propLen)) >= *propLen) {
23829585STim.Szeto@Sun.COM 					*propLen = reqLen + 1;
23839585STim.Szeto@Sun.COM 					return (STMF_ERROR_INVALID_ARG);
23849585STim.Szeto@Sun.COM 				}
23859585STim.Szeto@Sun.COM 			}
23869585STim.Szeto@Sun.COM 			break;
23879585STim.Szeto@Sun.COM 		case STMF_LU_PROP_WRITE_CACHE_DISABLE:
23889585STim.Szeto@Sun.COM 			if (diskLu->writebackCacheDisableValid == B_FALSE) {
23899585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
23909585STim.Szeto@Sun.COM 			}
23919585STim.Szeto@Sun.COM 			if (diskLu->writebackCacheDisable) {
23929585STim.Szeto@Sun.COM 				if ((reqLen = strlcpy(propVal, "true",
23939585STim.Szeto@Sun.COM 				    *propLen)) >= *propLen) {
23949585STim.Szeto@Sun.COM 					*propLen = reqLen + 1;
23959585STim.Szeto@Sun.COM 					return (STMF_ERROR_INVALID_ARG);
23969585STim.Szeto@Sun.COM 				}
23979585STim.Szeto@Sun.COM 			} else {
23989585STim.Szeto@Sun.COM 				if ((reqLen = strlcpy(propVal, "false",
23999585STim.Szeto@Sun.COM 				    *propLen)) >= *propLen) {
24009585STim.Szeto@Sun.COM 					*propLen = reqLen + 1;
24019585STim.Szeto@Sun.COM 					return (STMF_ERROR_INVALID_ARG);
24029585STim.Szeto@Sun.COM 				}
24039585STim.Szeto@Sun.COM 			}
24049585STim.Szeto@Sun.COM 			break;
24059585STim.Szeto@Sun.COM 		default:
24069585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NO_PROP;
24079585STim.Szeto@Sun.COM 			break;
24089585STim.Szeto@Sun.COM 	}
24099585STim.Szeto@Sun.COM 
24109585STim.Szeto@Sun.COM 	return (ret);
24119585STim.Szeto@Sun.COM }
24129585STim.Szeto@Sun.COM 
24139585STim.Szeto@Sun.COM /*
24149585STim.Szeto@Sun.COM  * setDiskProp
24159585STim.Szeto@Sun.COM  *
24169585STim.Szeto@Sun.COM  * Purpose: set properties for resource of type disk
24179585STim.Szeto@Sun.COM  *
24189585STim.Szeto@Sun.COM  * hdl - allocated luResourceImpl
24199585STim.Szeto@Sun.COM  * resourceProp - valid resource identifier
24209585STim.Szeto@Sun.COM  * propVal - valid resource value
24219585STim.Szeto@Sun.COM  */
24229585STim.Szeto@Sun.COM static int
24239585STim.Szeto@Sun.COM setDiskProp(luResourceImpl *hdl, uint32_t resourceProp, const char *propVal)
24249585STim.Szeto@Sun.COM {
24259585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
24269585STim.Szeto@Sun.COM 	int i;
24279585STim.Szeto@Sun.COM 	diskResource *diskLu = hdl->resource;
24289585STim.Szeto@Sun.COM 	unsigned long long numericProp = 0;
24299585STim.Szeto@Sun.COM 	char guidProp[LU_ASCII_GUID_SIZE + 1];
24309585STim.Szeto@Sun.COM 	char ouiProp[OUI_ASCII_SIZE + 1];
24319585STim.Szeto@Sun.COM 	unsigned int oui[OUI_SIZE];
24329585STim.Szeto@Sun.COM 	unsigned int guid[LU_GUID_SIZE];
24339585STim.Szeto@Sun.COM 	int propSize;
24349585STim.Szeto@Sun.COM 
24359585STim.Szeto@Sun.COM 
24369585STim.Szeto@Sun.COM 	if (propVal == NULL) {
24379585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
24389585STim.Szeto@Sun.COM 	}
24399585STim.Szeto@Sun.COM 
24409585STim.Szeto@Sun.COM 	switch (resourceProp) {
24419585STim.Szeto@Sun.COM 		case STMF_LU_PROP_ALIAS:
24429585STim.Szeto@Sun.COM 			if (strlcpy(diskLu->luAlias, propVal,
24439585STim.Szeto@Sun.COM 			    sizeof (diskLu->luAlias)) >=
24449585STim.Szeto@Sun.COM 			    sizeof (diskLu->luAlias)) {
24459585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
24469585STim.Szeto@Sun.COM 			}
24479585STim.Szeto@Sun.COM 			diskLu->luAliasValid = B_TRUE;
24489585STim.Szeto@Sun.COM 			break;
24499585STim.Szeto@Sun.COM 		case STMF_LU_PROP_BLOCK_SIZE:
24509585STim.Szeto@Sun.COM 			(void) sscanf(propVal, "%llu", &numericProp);
24519585STim.Szeto@Sun.COM 			if (numericProp > UINT16_MAX) {
24529585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
24539585STim.Szeto@Sun.COM 			}
24549585STim.Szeto@Sun.COM 			diskLu->blkSize = numericProp;
24559585STim.Szeto@Sun.COM 			diskLu->blkSizeValid = B_TRUE;
24569585STim.Szeto@Sun.COM 			break;
24579585STim.Szeto@Sun.COM 		case STMF_LU_PROP_COMPANY_ID:
24589585STim.Szeto@Sun.COM 			if ((strlcpy(ouiProp, propVal, sizeof (ouiProp))) >=
24599585STim.Szeto@Sun.COM 			    sizeof (ouiProp)) {
24609585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
24619585STim.Szeto@Sun.COM 			}
24629585STim.Szeto@Sun.COM 			if (checkHexUpper(ouiProp) != 0) {
24639585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
24649585STim.Szeto@Sun.COM 			}
24659585STim.Szeto@Sun.COM 			(void) sscanf(ouiProp, "%2X%2X%2X",
24669585STim.Szeto@Sun.COM 			    &oui[0], &oui[1], &oui[2]);
24679585STim.Szeto@Sun.COM 
24689585STim.Szeto@Sun.COM 			diskLu->companyId = 0;
24699585STim.Szeto@Sun.COM 			diskLu->companyId += oui[0] << 16;
24709585STim.Szeto@Sun.COM 			diskLu->companyId += oui[1] << 8;
24719585STim.Szeto@Sun.COM 			diskLu->companyId += oui[2];
24729585STim.Szeto@Sun.COM 			diskLu->companyIdValid = B_TRUE;
24739585STim.Szeto@Sun.COM 			break;
24749585STim.Szeto@Sun.COM 		case STMF_LU_PROP_GUID:
24759585STim.Szeto@Sun.COM 			if (strlen(propVal) != LU_ASCII_GUID_SIZE) {
24769585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
24779585STim.Szeto@Sun.COM 			}
24789585STim.Szeto@Sun.COM 
24799585STim.Szeto@Sun.COM 			if ((strlcpy(guidProp, propVal, sizeof (guidProp))) >=
24809585STim.Szeto@Sun.COM 			    sizeof (guidProp)) {
24819585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
24829585STim.Szeto@Sun.COM 			}
24839585STim.Szeto@Sun.COM 
24849585STim.Szeto@Sun.COM 			if (checkHexUpper(guidProp) != 0) {
24859585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
24869585STim.Szeto@Sun.COM 			}
24879585STim.Szeto@Sun.COM 
24889585STim.Szeto@Sun.COM 			(void) sscanf(guidProp,
24899585STim.Szeto@Sun.COM 			    "%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X",
24909585STim.Szeto@Sun.COM 			    &guid[0], &guid[1], &guid[2], &guid[3], &guid[4],
24919585STim.Szeto@Sun.COM 			    &guid[5], &guid[6], &guid[7], &guid[8], &guid[9],
24929585STim.Szeto@Sun.COM 			    &guid[10], &guid[11], &guid[12], &guid[13],
24939585STim.Szeto@Sun.COM 			    &guid[14], &guid[15]);
24949585STim.Szeto@Sun.COM 			for (i = 0; i < sizeof (diskLu->luGuid); i++) {
24959585STim.Szeto@Sun.COM 				diskLu->luGuid[i] = guid[i];
24969585STim.Szeto@Sun.COM 			}
24979585STim.Szeto@Sun.COM 			diskLu->luGuidValid = B_TRUE;
24989585STim.Szeto@Sun.COM 			break;
24999585STim.Szeto@Sun.COM 		case STMF_LU_PROP_FILENAME:
25009585STim.Szeto@Sun.COM 			if ((strlcpy(diskLu->luDataFileName, propVal,
25019585STim.Szeto@Sun.COM 			    sizeof (diskLu->luDataFileName))) >=
25029585STim.Szeto@Sun.COM 			    sizeof (diskLu->luDataFileName)) {
25039585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
25049585STim.Szeto@Sun.COM 			}
25059585STim.Szeto@Sun.COM 			diskLu->luDataFileNameValid = B_TRUE;
25069585STim.Szeto@Sun.COM 			break;
25079585STim.Szeto@Sun.COM 		case STMF_LU_PROP_META_FILENAME:
25089585STim.Szeto@Sun.COM 			if ((strlcpy(diskLu->luMetaFileName, propVal,
25099585STim.Szeto@Sun.COM 			    sizeof (diskLu->luMetaFileName))) >=
25109585STim.Szeto@Sun.COM 			    sizeof (diskLu->luMetaFileName)) {
25119585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
25129585STim.Szeto@Sun.COM 			}
25139585STim.Szeto@Sun.COM 			diskLu->luMetaFileNameValid = B_TRUE;
25149585STim.Szeto@Sun.COM 			break;
251510113SNattuvetty.Bhavyan@Sun.COM 		case STMF_LU_PROP_MGMT_URL:
251610113SNattuvetty.Bhavyan@Sun.COM 			if ((strlcpy(diskLu->luMgmtUrl, propVal,
251710113SNattuvetty.Bhavyan@Sun.COM 			    sizeof (diskLu->luMgmtUrl))) >=
251810113SNattuvetty.Bhavyan@Sun.COM 			    sizeof (diskLu->luMgmtUrl)) {
251910113SNattuvetty.Bhavyan@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
252010113SNattuvetty.Bhavyan@Sun.COM 			}
252110113SNattuvetty.Bhavyan@Sun.COM 			diskLu->luMgmtUrlValid = B_TRUE;
252210113SNattuvetty.Bhavyan@Sun.COM 			break;
25239585STim.Szeto@Sun.COM 		case STMF_LU_PROP_PID:
25249585STim.Szeto@Sun.COM 			if ((propSize = strlen(propVal)) >
25259585STim.Szeto@Sun.COM 			    sizeof (diskLu->pid)) {
25269585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
25279585STim.Szeto@Sun.COM 			}
25289585STim.Szeto@Sun.COM 			(void) strncpy(diskLu->pid, propVal, propSize);
25299585STim.Szeto@Sun.COM 			diskLu->pidValid = B_TRUE;
25309585STim.Szeto@Sun.COM 			break;
25319585STim.Szeto@Sun.COM 		case STMF_LU_PROP_SERIAL_NUM:
25329585STim.Szeto@Sun.COM 			if ((propSize = strlen(propVal)) >
25339585STim.Szeto@Sun.COM 			    (sizeof (diskLu->serialNum) - 1)) {
25349585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
25359585STim.Szeto@Sun.COM 			}
25369585STim.Szeto@Sun.COM 			(void) strncpy(diskLu->serialNum, propVal, propSize);
25379585STim.Szeto@Sun.COM 			diskLu->serialNumValid = B_TRUE;
25389585STim.Szeto@Sun.COM 			break;
25399585STim.Szeto@Sun.COM 		case STMF_LU_PROP_SIZE:
25409585STim.Szeto@Sun.COM 			if ((niceStrToNum(propVal, &diskLu->luSize) != 0)) {
25419585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
25429585STim.Szeto@Sun.COM 			}
25439585STim.Szeto@Sun.COM 			diskLu->luSizeValid = B_TRUE;
25449585STim.Szeto@Sun.COM 			break;
25459585STim.Szeto@Sun.COM 		case STMF_LU_PROP_VID:
25469585STim.Szeto@Sun.COM 			if ((propSize = strlen(propVal)) >
25479585STim.Szeto@Sun.COM 			    sizeof (diskLu->vid)) {
25489585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
25499585STim.Szeto@Sun.COM 			}
25509585STim.Szeto@Sun.COM 			(void) strncpy(diskLu->vid, propVal, propSize);
25519585STim.Szeto@Sun.COM 			diskLu->vidValid = B_TRUE;
25529585STim.Szeto@Sun.COM 			break;
25539585STim.Szeto@Sun.COM 		case STMF_LU_PROP_WRITE_PROTECT:
25549585STim.Szeto@Sun.COM 			if (strcasecmp(propVal, "TRUE") == 0) {
25559585STim.Szeto@Sun.COM 				diskLu->writeProtectEnable = B_TRUE;
25569585STim.Szeto@Sun.COM 			} else if (strcasecmp(propVal, "FALSE") == 0) {
25579585STim.Szeto@Sun.COM 				diskLu->writeProtectEnable = B_FALSE;
25589585STim.Szeto@Sun.COM 			} else {
25599585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
25609585STim.Szeto@Sun.COM 			}
25619585STim.Szeto@Sun.COM 			diskLu->writeProtectEnableValid = B_TRUE;
25629585STim.Szeto@Sun.COM 			break;
25639585STim.Szeto@Sun.COM 		case STMF_LU_PROP_WRITE_CACHE_DISABLE:
25649585STim.Szeto@Sun.COM 			if (strcasecmp(propVal, "TRUE") == 0) {
25659585STim.Szeto@Sun.COM 				diskLu->writebackCacheDisable = B_TRUE;
25669585STim.Szeto@Sun.COM 			} else if (strcasecmp(propVal, "FALSE") == 0) {
25679585STim.Szeto@Sun.COM 				diskLu->writebackCacheDisable = B_FALSE;
25689585STim.Szeto@Sun.COM 			} else {
25699585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
25709585STim.Szeto@Sun.COM 			}
25719585STim.Szeto@Sun.COM 			diskLu->writebackCacheDisableValid = B_TRUE;
25729585STim.Szeto@Sun.COM 			break;
25739585STim.Szeto@Sun.COM 		default:
25749585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NO_PROP;
25759585STim.Szeto@Sun.COM 			break;
25769585STim.Szeto@Sun.COM 	}
25779585STim.Szeto@Sun.COM 	return (ret);
25789585STim.Szeto@Sun.COM }
25799585STim.Szeto@Sun.COM 
25809585STim.Szeto@Sun.COM static int
25819585STim.Szeto@Sun.COM checkHexUpper(char *buf)
25829585STim.Szeto@Sun.COM {
25839585STim.Szeto@Sun.COM 	int i;
25849585STim.Szeto@Sun.COM 
25859585STim.Szeto@Sun.COM 	for (i = 0; i < strlen(buf); i++) {
25869585STim.Szeto@Sun.COM 		if (isxdigit(buf[i])) {
25879585STim.Szeto@Sun.COM 			buf[i] = toupper(buf[i]);
25889585STim.Szeto@Sun.COM 			continue;
25899585STim.Szeto@Sun.COM 		}
25909585STim.Szeto@Sun.COM 		return (-1);
25919585STim.Szeto@Sun.COM 	}
25929585STim.Szeto@Sun.COM 
25939585STim.Szeto@Sun.COM 	return (0);
25949585STim.Szeto@Sun.COM }
25959585STim.Szeto@Sun.COM 
25969585STim.Szeto@Sun.COM /*
25979585STim.Szeto@Sun.COM  * Given a numeric suffix, convert the value into a number of bits that the
25989585STim.Szeto@Sun.COM  * resulting value must be shifted.
25999585STim.Szeto@Sun.COM  * Code lifted from libzfs_util.c
26009585STim.Szeto@Sun.COM  */
26019585STim.Szeto@Sun.COM static int
26029585STim.Szeto@Sun.COM strToShift(const char *buf)
26039585STim.Szeto@Sun.COM {
26049585STim.Szeto@Sun.COM 	const char *ends = "BKMGTPE";
26059585STim.Szeto@Sun.COM 	int i;
26069585STim.Szeto@Sun.COM 
26079585STim.Szeto@Sun.COM 	if (buf[0] == '\0')
26089585STim.Szeto@Sun.COM 		return (0);
26099585STim.Szeto@Sun.COM 
26109585STim.Szeto@Sun.COM 	for (i = 0; i < strlen(ends); i++) {
26119585STim.Szeto@Sun.COM 		if (toupper(buf[0]) == ends[i])
26129585STim.Szeto@Sun.COM 			return (10*i);
26139585STim.Szeto@Sun.COM 	}
26149585STim.Szeto@Sun.COM 
26159585STim.Szeto@Sun.COM 	return (-1);
26169585STim.Szeto@Sun.COM }
26179585STim.Szeto@Sun.COM 
26189585STim.Szeto@Sun.COM int
26199585STim.Szeto@Sun.COM stmfFreeLuResource(luResource hdl)
26209585STim.Szeto@Sun.COM {
26219585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
26229585STim.Szeto@Sun.COM 	if (hdl == NULL) {
26239585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
26249585STim.Szeto@Sun.COM 	}
26259585STim.Szeto@Sun.COM 
26269585STim.Szeto@Sun.COM 	luResourceImpl *hdlImpl = hdl;
26279585STim.Szeto@Sun.COM 	free(hdlImpl->resource);
26289585STim.Szeto@Sun.COM 	free(hdlImpl);
26299585STim.Szeto@Sun.COM 	return (ret);
26309585STim.Szeto@Sun.COM }
26319585STim.Szeto@Sun.COM 
26329585STim.Szeto@Sun.COM /*
26339585STim.Szeto@Sun.COM  * Convert a string of the form '100G' into a real number. Used when setting
26349585STim.Szeto@Sun.COM  * the size of a logical unit.
26359585STim.Szeto@Sun.COM  * Code lifted from libzfs_util.c
26369585STim.Szeto@Sun.COM  */
26379585STim.Szeto@Sun.COM static int
26389585STim.Szeto@Sun.COM niceStrToNum(const char *value, uint64_t *num)
26399585STim.Szeto@Sun.COM {
26409585STim.Szeto@Sun.COM 	char *end;
26419585STim.Szeto@Sun.COM 	int shift;
26429585STim.Szeto@Sun.COM 
26439585STim.Szeto@Sun.COM 	*num = 0;
26449585STim.Szeto@Sun.COM 
26459585STim.Szeto@Sun.COM 	/* Check to see if this looks like a number.  */
26469585STim.Szeto@Sun.COM 	if ((value[0] < '0' || value[0] > '9') && value[0] != '.') {
26479585STim.Szeto@Sun.COM 		return (-1);
26489585STim.Szeto@Sun.COM 	}
26499585STim.Szeto@Sun.COM 
26509585STim.Szeto@Sun.COM 	/* Rely on stroull() to process the numeric portion.  */
26519585STim.Szeto@Sun.COM 	errno = 0;
26529585STim.Szeto@Sun.COM 	*num = strtoull(value, &end, 10);
26539585STim.Szeto@Sun.COM 
26549585STim.Szeto@Sun.COM 	/*
26559585STim.Szeto@Sun.COM 	 * Check for ERANGE, which indicates that the value is too large to fit
26569585STim.Szeto@Sun.COM 	 * in a 64-bit value.
26579585STim.Szeto@Sun.COM 	 */
26589585STim.Szeto@Sun.COM 	if (errno == ERANGE) {
26599585STim.Szeto@Sun.COM 		return (-1);
26609585STim.Szeto@Sun.COM 	}
26619585STim.Szeto@Sun.COM 
26629585STim.Szeto@Sun.COM 	/*
26639585STim.Szeto@Sun.COM 	 * If we have a decimal value, then do the computation with floating
26649585STim.Szeto@Sun.COM 	 * point arithmetic.  Otherwise, use standard arithmetic.
26659585STim.Szeto@Sun.COM 	 */
26669585STim.Szeto@Sun.COM 	if (*end == '.') {
26679585STim.Szeto@Sun.COM 		double fval = strtod(value, &end);
26689585STim.Szeto@Sun.COM 
26699585STim.Szeto@Sun.COM 		if ((shift = strToShift(end)) == -1) {
26709585STim.Szeto@Sun.COM 			return (-1);
26719585STim.Szeto@Sun.COM 		}
26729585STim.Szeto@Sun.COM 
26739585STim.Szeto@Sun.COM 		fval *= pow(2, shift);
26749585STim.Szeto@Sun.COM 
26759585STim.Szeto@Sun.COM 		if (fval > UINT64_MAX) {
26769585STim.Szeto@Sun.COM 			return (-1);
26779585STim.Szeto@Sun.COM 		}
26789585STim.Szeto@Sun.COM 
26799585STim.Szeto@Sun.COM 		*num = (uint64_t)fval;
26809585STim.Szeto@Sun.COM 	} else {
26819585STim.Szeto@Sun.COM 		if ((shift = strToShift(end)) == -1) {
26829585STim.Szeto@Sun.COM 			return (-1);
26839585STim.Szeto@Sun.COM 		}
26849585STim.Szeto@Sun.COM 
26859585STim.Szeto@Sun.COM 		/* Check for overflow */
26869585STim.Szeto@Sun.COM 		if (shift >= 64 || (*num << shift) >> shift != *num) {
26879585STim.Szeto@Sun.COM 			return (-1);
26889585STim.Szeto@Sun.COM 		}
26899585STim.Szeto@Sun.COM 
26909585STim.Szeto@Sun.COM 		*num <<= shift;
26919585STim.Szeto@Sun.COM 	}
26929585STim.Szeto@Sun.COM 
26939585STim.Szeto@Sun.COM 	return (0);
26949585STim.Szeto@Sun.COM }
26959585STim.Szeto@Sun.COM 
26969585STim.Szeto@Sun.COM /*
26977836SJohn.Forte@Sun.COM  * stmfCreateTargetGroup
26987836SJohn.Forte@Sun.COM  *
26997836SJohn.Forte@Sun.COM  * Purpose: Create a local port group
27007836SJohn.Forte@Sun.COM  *
27017836SJohn.Forte@Sun.COM  * targetGroupName - name of local port group to create
27027836SJohn.Forte@Sun.COM  */
27037836SJohn.Forte@Sun.COM int
27047836SJohn.Forte@Sun.COM stmfCreateTargetGroup(stmfGroupName *targetGroupName)
27057836SJohn.Forte@Sun.COM {
27067836SJohn.Forte@Sun.COM 	int ret;
27077836SJohn.Forte@Sun.COM 	int fd;
27087836SJohn.Forte@Sun.COM 
27097836SJohn.Forte@Sun.COM 	if (targetGroupName == NULL ||
27107836SJohn.Forte@Sun.COM 	    (strnlen((char *)targetGroupName, sizeof (stmfGroupName))
27117836SJohn.Forte@Sun.COM 	    == sizeof (stmfGroupName))) {
27127836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
27137836SJohn.Forte@Sun.COM 	}
27147836SJohn.Forte@Sun.COM 
27157836SJohn.Forte@Sun.COM 	/* Check to ensure service exists */
27167836SJohn.Forte@Sun.COM 	if (psCheckService() != STMF_STATUS_SUCCESS) {
27177836SJohn.Forte@Sun.COM 		return (STMF_ERROR_SERVICE_NOT_FOUND);
27187836SJohn.Forte@Sun.COM 	}
27197836SJohn.Forte@Sun.COM 
27207836SJohn.Forte@Sun.COM 	/* call init */
27217836SJohn.Forte@Sun.COM 	ret = initializeConfig();
27227836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
27237836SJohn.Forte@Sun.COM 		return (ret);
27247836SJohn.Forte@Sun.COM 	}
27257836SJohn.Forte@Sun.COM 
27267836SJohn.Forte@Sun.COM 	/*
27277836SJohn.Forte@Sun.COM 	 * Open control node for stmf
27287836SJohn.Forte@Sun.COM 	 */
27297836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
27307836SJohn.Forte@Sun.COM 		return (ret);
27317836SJohn.Forte@Sun.COM 
27327836SJohn.Forte@Sun.COM 	/*
27337836SJohn.Forte@Sun.COM 	 * Add the group to the driver
27347836SJohn.Forte@Sun.COM 	 */
27357836SJohn.Forte@Sun.COM 	if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_TARGET_GROUP,
27367836SJohn.Forte@Sun.COM 	    targetGroupName)) != STMF_STATUS_SUCCESS) {
27377836SJohn.Forte@Sun.COM 		goto done;
27387836SJohn.Forte@Sun.COM 	}
27397836SJohn.Forte@Sun.COM 
27409585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
27419585STim.Szeto@Sun.COM 		goto done;
27429585STim.Szeto@Sun.COM 	}
27439585STim.Szeto@Sun.COM 
27447836SJohn.Forte@Sun.COM 	/*
27457836SJohn.Forte@Sun.COM 	 * If the add to the driver was successful, add it to the persistent
27467836SJohn.Forte@Sun.COM 	 * store.
27477836SJohn.Forte@Sun.COM 	 */
27487836SJohn.Forte@Sun.COM 	ret = psCreateTargetGroup((char *)targetGroupName);
27497836SJohn.Forte@Sun.COM 	switch (ret) {
27507836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
27517836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
27527836SJohn.Forte@Sun.COM 			break;
27537836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_EXISTS:
27547836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_EXISTS;
27557836SJohn.Forte@Sun.COM 			break;
27567836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
27577836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
27587836SJohn.Forte@Sun.COM 			break;
27597836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
27607836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
27617836SJohn.Forte@Sun.COM 			break;
27627836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
27637836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
27647836SJohn.Forte@Sun.COM 			break;
27657836SJohn.Forte@Sun.COM 		default:
27667836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
27677836SJohn.Forte@Sun.COM 			    "stmfCreateTargetGroup:psCreateTargetGroup"
27687836SJohn.Forte@Sun.COM 			    ":error(%d)", ret);
27697836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
27707836SJohn.Forte@Sun.COM 			break;
27717836SJohn.Forte@Sun.COM 	}
27727836SJohn.Forte@Sun.COM 
27737836SJohn.Forte@Sun.COM done:
27747836SJohn.Forte@Sun.COM 	(void) close(fd);
27757836SJohn.Forte@Sun.COM 	return (ret);
27767836SJohn.Forte@Sun.COM }
27777836SJohn.Forte@Sun.COM 
27787836SJohn.Forte@Sun.COM /*
27797836SJohn.Forte@Sun.COM  * stmfDeleteHostGroup
27807836SJohn.Forte@Sun.COM  *
27817836SJohn.Forte@Sun.COM  * Purpose: Delete an initiator or local port group
27827836SJohn.Forte@Sun.COM  *
27837836SJohn.Forte@Sun.COM  * hostGroupName - group to delete
27847836SJohn.Forte@Sun.COM  */
27857836SJohn.Forte@Sun.COM int
27867836SJohn.Forte@Sun.COM stmfDeleteHostGroup(stmfGroupName *hostGroupName)
27877836SJohn.Forte@Sun.COM {
27887836SJohn.Forte@Sun.COM 	int ret;
27897836SJohn.Forte@Sun.COM 	int fd;
27907836SJohn.Forte@Sun.COM 
27917836SJohn.Forte@Sun.COM 	if (hostGroupName == NULL) {
27927836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
27937836SJohn.Forte@Sun.COM 	}
27947836SJohn.Forte@Sun.COM 
27957836SJohn.Forte@Sun.COM 	/* Check to ensure service exists */
27967836SJohn.Forte@Sun.COM 	if (psCheckService() != STMF_STATUS_SUCCESS) {
27977836SJohn.Forte@Sun.COM 		return (STMF_ERROR_SERVICE_NOT_FOUND);
27987836SJohn.Forte@Sun.COM 	}
27997836SJohn.Forte@Sun.COM 
28007836SJohn.Forte@Sun.COM 	/* call init */
28017836SJohn.Forte@Sun.COM 	ret = initializeConfig();
28027836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
28037836SJohn.Forte@Sun.COM 		return (ret);
28047836SJohn.Forte@Sun.COM 	}
28057836SJohn.Forte@Sun.COM 
28067836SJohn.Forte@Sun.COM 	/*
28077836SJohn.Forte@Sun.COM 	 * Open control node for stmf
28087836SJohn.Forte@Sun.COM 	 */
28097836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
28107836SJohn.Forte@Sun.COM 		return (ret);
28117836SJohn.Forte@Sun.COM 
28127836SJohn.Forte@Sun.COM 	/*
28137836SJohn.Forte@Sun.COM 	 * Remove the group from the driver
28147836SJohn.Forte@Sun.COM 	 */
28157836SJohn.Forte@Sun.COM 	if ((ret = groupIoctl(fd, STMF_IOCTL_REMOVE_HOST_GROUP,
28167836SJohn.Forte@Sun.COM 	    hostGroupName)) != STMF_STATUS_SUCCESS) {
28177836SJohn.Forte@Sun.COM 		goto done;
28187836SJohn.Forte@Sun.COM 	}
28197836SJohn.Forte@Sun.COM 
28209585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
28219585STim.Szeto@Sun.COM 		goto done;
28229585STim.Szeto@Sun.COM 	}
28239585STim.Szeto@Sun.COM 
28247836SJohn.Forte@Sun.COM 	/*
28257836SJohn.Forte@Sun.COM 	 * If the remove from the driver was successful, remove it from the
28267836SJohn.Forte@Sun.COM 	 * persistent store.
28277836SJohn.Forte@Sun.COM 	 */
28287836SJohn.Forte@Sun.COM 	ret = psDeleteHostGroup((char *)hostGroupName);
28297836SJohn.Forte@Sun.COM 	switch (ret) {
28307836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
28317836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
28327836SJohn.Forte@Sun.COM 			break;
28337836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
28347836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
28357836SJohn.Forte@Sun.COM 			break;
28367836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
28377836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
28387836SJohn.Forte@Sun.COM 			break;
28397836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
28407836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
28417836SJohn.Forte@Sun.COM 			break;
28427836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
28437836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
28447836SJohn.Forte@Sun.COM 			break;
28457836SJohn.Forte@Sun.COM 		default:
28467836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
28477836SJohn.Forte@Sun.COM 			    "stmfDeleteHostGroup:psDeleteHostGroup:error(%d)",
28487836SJohn.Forte@Sun.COM 			    ret);
28497836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
28507836SJohn.Forte@Sun.COM 			break;
28517836SJohn.Forte@Sun.COM 	}
28527836SJohn.Forte@Sun.COM 
28537836SJohn.Forte@Sun.COM done:
28547836SJohn.Forte@Sun.COM 	(void) close(fd);
28557836SJohn.Forte@Sun.COM 	return (ret);
28567836SJohn.Forte@Sun.COM }
28577836SJohn.Forte@Sun.COM 
28587836SJohn.Forte@Sun.COM /*
28597836SJohn.Forte@Sun.COM  * stmfDeleteTargetGroup
28607836SJohn.Forte@Sun.COM  *
28617836SJohn.Forte@Sun.COM  * Purpose: Delete an initiator or local port group
28627836SJohn.Forte@Sun.COM  *
28637836SJohn.Forte@Sun.COM  * targetGroupName - group to delete
28647836SJohn.Forte@Sun.COM  */
28657836SJohn.Forte@Sun.COM int
28667836SJohn.Forte@Sun.COM stmfDeleteTargetGroup(stmfGroupName *targetGroupName)
28677836SJohn.Forte@Sun.COM {
28687836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
28697836SJohn.Forte@Sun.COM 	int fd;
28707836SJohn.Forte@Sun.COM 
28717836SJohn.Forte@Sun.COM 	if (targetGroupName == NULL) {
28727836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
28737836SJohn.Forte@Sun.COM 	}
28747836SJohn.Forte@Sun.COM 
28757836SJohn.Forte@Sun.COM 	/* Check to ensure service exists */
28767836SJohn.Forte@Sun.COM 	if (psCheckService() != STMF_STATUS_SUCCESS) {
28777836SJohn.Forte@Sun.COM 		return (STMF_ERROR_SERVICE_NOT_FOUND);
28787836SJohn.Forte@Sun.COM 	}
28797836SJohn.Forte@Sun.COM 
28807836SJohn.Forte@Sun.COM 	/* call init */
28817836SJohn.Forte@Sun.COM 	ret = initializeConfig();
28827836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
28837836SJohn.Forte@Sun.COM 		return (ret);
28847836SJohn.Forte@Sun.COM 	}
28857836SJohn.Forte@Sun.COM 
28867836SJohn.Forte@Sun.COM 	/*
28877836SJohn.Forte@Sun.COM 	 * Open control node for stmf
28887836SJohn.Forte@Sun.COM 	 */
28897836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
28907836SJohn.Forte@Sun.COM 		return (ret);
28917836SJohn.Forte@Sun.COM 
28927836SJohn.Forte@Sun.COM 	/*
28937836SJohn.Forte@Sun.COM 	 * Remove the group from the driver
28947836SJohn.Forte@Sun.COM 	 */
28957836SJohn.Forte@Sun.COM 	if ((ret = groupIoctl(fd, STMF_IOCTL_REMOVE_TARGET_GROUP,
28967836SJohn.Forte@Sun.COM 	    targetGroupName)) != STMF_STATUS_SUCCESS) {
28977836SJohn.Forte@Sun.COM 		goto done;
28987836SJohn.Forte@Sun.COM 	}
28997836SJohn.Forte@Sun.COM 
29009585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
29019585STim.Szeto@Sun.COM 		goto done;
29029585STim.Szeto@Sun.COM 	}
29039585STim.Szeto@Sun.COM 
29047836SJohn.Forte@Sun.COM 	/*
29057836SJohn.Forte@Sun.COM 	 * If the remove from the driver was successful, remove it from the
29067836SJohn.Forte@Sun.COM 	 * persistent store.
29077836SJohn.Forte@Sun.COM 	 */
29087836SJohn.Forte@Sun.COM 	ret = psDeleteTargetGroup((char *)targetGroupName);
29097836SJohn.Forte@Sun.COM 	switch (ret) {
29107836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
29117836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
29127836SJohn.Forte@Sun.COM 			break;
29137836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
29147836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
29157836SJohn.Forte@Sun.COM 			break;
29167836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
29177836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
29187836SJohn.Forte@Sun.COM 			break;
29197836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
29207836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
29217836SJohn.Forte@Sun.COM 			break;
29227836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
29237836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
29247836SJohn.Forte@Sun.COM 			break;
29257836SJohn.Forte@Sun.COM 		default:
29267836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
29277836SJohn.Forte@Sun.COM 			    "stmfDeleteTargetGroup:psDeleteTargetGroup"
29287836SJohn.Forte@Sun.COM 			    ":error(%d)", ret);
29297836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
29307836SJohn.Forte@Sun.COM 			break;
29317836SJohn.Forte@Sun.COM 	}
29327836SJohn.Forte@Sun.COM 
29337836SJohn.Forte@Sun.COM done:
29347836SJohn.Forte@Sun.COM 	(void) close(fd);
29357836SJohn.Forte@Sun.COM 	return (ret);
29367836SJohn.Forte@Sun.COM }
29377836SJohn.Forte@Sun.COM 
29387836SJohn.Forte@Sun.COM /*
29397836SJohn.Forte@Sun.COM  * stmfDevidFromIscsiName
29407836SJohn.Forte@Sun.COM  *
29417836SJohn.Forte@Sun.COM  * Purpose: convert an iSCSI name to an stmf devid
29427836SJohn.Forte@Sun.COM  *
29437836SJohn.Forte@Sun.COM  * iscsiName - unicode nul terminated utf-8 encoded iSCSI name
29447836SJohn.Forte@Sun.COM  * devid - on success, contains the converted iscsi name
29457836SJohn.Forte@Sun.COM  */
29467836SJohn.Forte@Sun.COM int
29477836SJohn.Forte@Sun.COM stmfDevidFromIscsiName(char *iscsiName, stmfDevid *devid)
29487836SJohn.Forte@Sun.COM {
29497836SJohn.Forte@Sun.COM 	if (devid == NULL || iscsiName == NULL)
29507836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
29517836SJohn.Forte@Sun.COM 
29527836SJohn.Forte@Sun.COM 	bzero(devid, sizeof (stmfDevid));
29537836SJohn.Forte@Sun.COM 
29547836SJohn.Forte@Sun.COM 	/* Validate size of target */
29557836SJohn.Forte@Sun.COM 	if ((devid->identLength = strlen(iscsiName)) > MAX_ISCSI_NAME ||
29567836SJohn.Forte@Sun.COM 	    devid->identLength < strlen(EUI) ||
29577836SJohn.Forte@Sun.COM 	    devid->identLength < strlen(IQN)) {
29587836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
29597836SJohn.Forte@Sun.COM 	}
29607836SJohn.Forte@Sun.COM 
29617836SJohn.Forte@Sun.COM 	if ((strncmp(iscsiName, EUI, strlen(EUI)) != 0) &&
29627836SJohn.Forte@Sun.COM 	    strncmp(iscsiName, IQN, strlen(IQN)) != 0) {
29637836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
29647836SJohn.Forte@Sun.COM 	}
29657836SJohn.Forte@Sun.COM 
29667836SJohn.Forte@Sun.COM 	/* copy UTF-8 bytes to ident */
29677836SJohn.Forte@Sun.COM 	bcopy(iscsiName, devid->ident, devid->identLength);
29687836SJohn.Forte@Sun.COM 
29697836SJohn.Forte@Sun.COM 	return (STMF_STATUS_SUCCESS);
29707836SJohn.Forte@Sun.COM }
29717836SJohn.Forte@Sun.COM 
29727836SJohn.Forte@Sun.COM /*
29737836SJohn.Forte@Sun.COM  * stmfDevidFromWwn
29747836SJohn.Forte@Sun.COM  *
29757836SJohn.Forte@Sun.COM  * Purpose: convert a WWN to an stmf devid
29767836SJohn.Forte@Sun.COM  *
29777836SJohn.Forte@Sun.COM  * wwn - 8-byte wwn identifier
29787836SJohn.Forte@Sun.COM  * devid - on success, contains the converted wwn
29797836SJohn.Forte@Sun.COM  */
29807836SJohn.Forte@Sun.COM int
29817836SJohn.Forte@Sun.COM stmfDevidFromWwn(uchar_t *wwn, stmfDevid *devid)
29827836SJohn.Forte@Sun.COM {
29837836SJohn.Forte@Sun.COM 	if (wwn == NULL || devid == NULL)
29847836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
29857836SJohn.Forte@Sun.COM 
29867836SJohn.Forte@Sun.COM 	bzero(devid, sizeof (stmfDevid));
29877836SJohn.Forte@Sun.COM 
29887836SJohn.Forte@Sun.COM 	/* Copy eui prefix */
29897836SJohn.Forte@Sun.COM 	(void) bcopy(WWN, devid->ident, strlen(WWN));
29907836SJohn.Forte@Sun.COM 
29917836SJohn.Forte@Sun.COM 	/* Convert to ASCII uppercase hexadecimal string */
29927836SJohn.Forte@Sun.COM 	(void) snprintf((char *)&devid->ident[strlen(WWN)],
29937836SJohn.Forte@Sun.COM 	    sizeof (devid->ident), "%02X%02X%02X%02X%02X%02X%02X%02X",
29947836SJohn.Forte@Sun.COM 	    wwn[0], wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]);
29957836SJohn.Forte@Sun.COM 
29967836SJohn.Forte@Sun.COM 	devid->identLength = strlen((char *)devid->ident);
29977836SJohn.Forte@Sun.COM 
29987836SJohn.Forte@Sun.COM 	return (STMF_STATUS_SUCCESS);
29997836SJohn.Forte@Sun.COM }
30007836SJohn.Forte@Sun.COM 
30017836SJohn.Forte@Sun.COM /*
30027836SJohn.Forte@Sun.COM  * stmfFreeMemory
30037836SJohn.Forte@Sun.COM  *
30047836SJohn.Forte@Sun.COM  * Purpose: Free memory allocated by this library
30057836SJohn.Forte@Sun.COM  *
30067836SJohn.Forte@Sun.COM  * memory - previously allocated pointer of memory managed by library
30077836SJohn.Forte@Sun.COM  */
30087836SJohn.Forte@Sun.COM void
30097836SJohn.Forte@Sun.COM stmfFreeMemory(void *memory)
30107836SJohn.Forte@Sun.COM {
30117836SJohn.Forte@Sun.COM 	free(memory);
30127836SJohn.Forte@Sun.COM }
30137836SJohn.Forte@Sun.COM 
30147836SJohn.Forte@Sun.COM /*
30159585STim.Szeto@Sun.COM  * get host group, target group list from stmf
30167836SJohn.Forte@Sun.COM  *
30179585STim.Szeto@Sun.COM  * groupType - HOST_GROUP, TARGET_GROUP
30187836SJohn.Forte@Sun.COM  */
30199585STim.Szeto@Sun.COM static int
30209585STim.Szeto@Sun.COM groupListIoctl(stmfGroupList **groupList, int groupType)
30219585STim.Szeto@Sun.COM {
30229585STim.Szeto@Sun.COM 	int ret;
30239585STim.Szeto@Sun.COM 	int fd;
30249585STim.Szeto@Sun.COM 	int ioctlRet;
30259585STim.Szeto@Sun.COM 	int i;
30269585STim.Szeto@Sun.COM 	int cmd;
30279585STim.Szeto@Sun.COM 	stmf_iocdata_t stmfIoctl;
30289585STim.Szeto@Sun.COM 	/* framework group list */
30299585STim.Szeto@Sun.COM 	stmf_group_name_t *iGroupList = NULL;
30309585STim.Szeto@Sun.COM 	uint32_t groupListSize;
30319585STim.Szeto@Sun.COM 
30329585STim.Szeto@Sun.COM 	if (groupList == NULL) {
30339585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
30349585STim.Szeto@Sun.COM 	}
30359585STim.Szeto@Sun.COM 
30369585STim.Szeto@Sun.COM 	if (groupType == HOST_GROUP) {
30379585STim.Szeto@Sun.COM 		cmd = STMF_IOCTL_GET_HG_LIST;
30389585STim.Szeto@Sun.COM 	} else if (groupType == TARGET_GROUP) {
30399585STim.Szeto@Sun.COM 		cmd = STMF_IOCTL_GET_TG_LIST;
30409585STim.Szeto@Sun.COM 	} else {
30419585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
30429585STim.Szeto@Sun.COM 	}
30439585STim.Szeto@Sun.COM 
30449585STim.Szeto@Sun.COM 	/* call init */
30459585STim.Szeto@Sun.COM 	ret = initializeConfig();
30469585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
30479585STim.Szeto@Sun.COM 		return (ret);
30489585STim.Szeto@Sun.COM 	}
30499585STim.Szeto@Sun.COM 
30509585STim.Szeto@Sun.COM 	/*
30519585STim.Szeto@Sun.COM 	 * Open control node for stmf
30529585STim.Szeto@Sun.COM 	 */
30539585STim.Szeto@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
30549585STim.Szeto@Sun.COM 		return (ret);
30559585STim.Szeto@Sun.COM 
30569585STim.Szeto@Sun.COM 	/*
30579585STim.Szeto@Sun.COM 	 * Allocate ioctl input buffer
30589585STim.Szeto@Sun.COM 	 */
30599585STim.Szeto@Sun.COM 	groupListSize = ALLOC_GROUP;
30609585STim.Szeto@Sun.COM 	groupListSize = groupListSize * (sizeof (stmf_group_name_t));
30619585STim.Szeto@Sun.COM 	iGroupList = (stmf_group_name_t *)calloc(1, groupListSize);
30629585STim.Szeto@Sun.COM 	if (iGroupList == NULL) {
30639585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
30649585STim.Szeto@Sun.COM 		goto done;
30659585STim.Szeto@Sun.COM 	}
30669585STim.Szeto@Sun.COM 
30679585STim.Szeto@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
30689585STim.Szeto@Sun.COM 	/*
30699585STim.Szeto@Sun.COM 	 * Issue ioctl to get the group list
30709585STim.Szeto@Sun.COM 	 */
30719585STim.Szeto@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
30729585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf_size = groupListSize;
30739585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupList;
30749585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
30759585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
30769585STim.Szeto@Sun.COM 		switch (errno) {
30779585STim.Szeto@Sun.COM 			case EBUSY:
30789585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
30799585STim.Szeto@Sun.COM 				break;
30809585STim.Szeto@Sun.COM 			case EPERM:
30819585STim.Szeto@Sun.COM 			case EACCES:
30829585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
30839585STim.Szeto@Sun.COM 				break;
30849585STim.Szeto@Sun.COM 			default:
30859585STim.Szeto@Sun.COM 				syslog(LOG_DEBUG,
30869585STim.Szeto@Sun.COM 				    "groupListIoctl:ioctl errno(%d)",
30879585STim.Szeto@Sun.COM 				    errno);
30889585STim.Szeto@Sun.COM 				ret = STMF_STATUS_ERROR;
30899585STim.Szeto@Sun.COM 				break;
30909585STim.Szeto@Sun.COM 		}
30919585STim.Szeto@Sun.COM 		goto done;
30929585STim.Szeto@Sun.COM 	}
30939585STim.Szeto@Sun.COM 	/*
30949585STim.Szeto@Sun.COM 	 * Check whether input buffer was large enough
30959585STim.Szeto@Sun.COM 	 */
30969585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_GROUP) {
30979585STim.Szeto@Sun.COM 		groupListSize = stmfIoctl.stmf_obuf_max_nentries *
30989585STim.Szeto@Sun.COM 		    sizeof (stmf_group_name_t);
30999585STim.Szeto@Sun.COM 		iGroupList = realloc(iGroupList, groupListSize);
31009585STim.Szeto@Sun.COM 		if (iGroupList == NULL) {
31019585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NOMEM;
31029585STim.Szeto@Sun.COM 			goto done;
31039585STim.Szeto@Sun.COM 		}
31049585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf_size = groupListSize;
31059585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupList;
31069585STim.Szeto@Sun.COM 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
31079585STim.Szeto@Sun.COM 		if (ioctlRet != 0) {
31089585STim.Szeto@Sun.COM 			switch (errno) {
31099585STim.Szeto@Sun.COM 				case EBUSY:
31109585STim.Szeto@Sun.COM 					ret = STMF_ERROR_BUSY;
31119585STim.Szeto@Sun.COM 					break;
31129585STim.Szeto@Sun.COM 				case EPERM:
31139585STim.Szeto@Sun.COM 				case EACCES:
31149585STim.Szeto@Sun.COM 					ret = STMF_ERROR_PERM;
31159585STim.Szeto@Sun.COM 					break;
31169585STim.Szeto@Sun.COM 				default:
31179585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
31189585STim.Szeto@Sun.COM 					    "groupListIoctl:ioctl errno(%d)",
31199585STim.Szeto@Sun.COM 					    errno);
31209585STim.Szeto@Sun.COM 					ret = STMF_STATUS_ERROR;
31219585STim.Szeto@Sun.COM 					break;
31229585STim.Szeto@Sun.COM 			}
31239585STim.Szeto@Sun.COM 			goto done;
31249585STim.Szeto@Sun.COM 		}
31259585STim.Szeto@Sun.COM 	}
31269585STim.Szeto@Sun.COM 
31279585STim.Szeto@Sun.COM 	/* allocate and copy to caller's buffer */
312810236SSrivijitha.Dugganapalli@Sun.COM 	*groupList = (stmfGroupList *)calloc(1, sizeof (stmfGroupList) +
312910236SSrivijitha.Dugganapalli@Sun.COM 	    sizeof (stmfGroupName) * stmfIoctl.stmf_obuf_nentries);
31309585STim.Szeto@Sun.COM 	if (*groupList == NULL) {
31319585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
31329585STim.Szeto@Sun.COM 		goto done;
31339585STim.Szeto@Sun.COM 	}
31349585STim.Szeto@Sun.COM 	(*groupList)->cnt = stmfIoctl.stmf_obuf_nentries;
31359585STim.Szeto@Sun.COM 	for (i = 0; i < stmfIoctl.stmf_obuf_nentries; i++) {
313610113SNattuvetty.Bhavyan@Sun.COM 		bcopy(iGroupList[i].name, (*groupList)->name[i],
31379585STim.Szeto@Sun.COM 		    sizeof (stmfGroupName));
31389585STim.Szeto@Sun.COM 	}
31399585STim.Szeto@Sun.COM 
31409585STim.Szeto@Sun.COM done:
31419585STim.Szeto@Sun.COM 	free(iGroupList);
31429585STim.Szeto@Sun.COM 	(void) close(fd);
31439585STim.Szeto@Sun.COM 	return (ret);
31449585STim.Szeto@Sun.COM }
31459585STim.Szeto@Sun.COM 
31469585STim.Szeto@Sun.COM /*
31479585STim.Szeto@Sun.COM  * get host group members, target group members from stmf
31489585STim.Szeto@Sun.COM  *
31499585STim.Szeto@Sun.COM  * groupProps - allocated on success
31509585STim.Szeto@Sun.COM  *
31519585STim.Szeto@Sun.COM  * groupType - HOST_GROUP, TARGET_GROUP
31529585STim.Szeto@Sun.COM  */
31539585STim.Szeto@Sun.COM static int
31549585STim.Szeto@Sun.COM groupMemberListIoctl(stmfGroupName *groupName, stmfGroupProperties **groupProps,
31559585STim.Szeto@Sun.COM     int groupType)
31567836SJohn.Forte@Sun.COM {
31577836SJohn.Forte@Sun.COM 	int ret;
31589585STim.Szeto@Sun.COM 	int fd;
31599585STim.Szeto@Sun.COM 	int ioctlRet;
31609585STim.Szeto@Sun.COM 	int i;
31619585STim.Szeto@Sun.COM 	int cmd;
31629585STim.Szeto@Sun.COM 	stmf_iocdata_t stmfIoctl;
31639585STim.Szeto@Sun.COM 	/* framework group list */
31649585STim.Szeto@Sun.COM 	stmf_group_name_t iGroupName;
31659585STim.Szeto@Sun.COM 	stmf_ge_ident_t *iGroupMembers;
31669585STim.Szeto@Sun.COM 	uint32_t groupListSize;
31679585STim.Szeto@Sun.COM 
31689585STim.Szeto@Sun.COM 	if (groupName == NULL) {
31699585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
31709585STim.Szeto@Sun.COM 	}
31719585STim.Szeto@Sun.COM 
31729585STim.Szeto@Sun.COM 	if (groupType == HOST_GROUP) {
31739585STim.Szeto@Sun.COM 		cmd = STMF_IOCTL_GET_HG_ENTRIES;
31749585STim.Szeto@Sun.COM 	} else if (groupType == TARGET_GROUP) {
31759585STim.Szeto@Sun.COM 		cmd = STMF_IOCTL_GET_TG_ENTRIES;
31769585STim.Szeto@Sun.COM 	} else {
31777836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
31787836SJohn.Forte@Sun.COM 	}
31797836SJohn.Forte@Sun.COM 
31809585STim.Szeto@Sun.COM 	/* call init */
31819585STim.Szeto@Sun.COM 	ret = initializeConfig();
31829585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
31839585STim.Szeto@Sun.COM 		return (ret);
31849585STim.Szeto@Sun.COM 	}
31859585STim.Szeto@Sun.COM 
31869585STim.Szeto@Sun.COM 	/*
31879585STim.Szeto@Sun.COM 	 * Open control node for stmf
31889585STim.Szeto@Sun.COM 	 */
31899585STim.Szeto@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
31909585STim.Szeto@Sun.COM 		return (ret);
31919585STim.Szeto@Sun.COM 
31929585STim.Szeto@Sun.COM 	bzero(&iGroupName, sizeof (iGroupName));
31939585STim.Szeto@Sun.COM 
31949585STim.Szeto@Sun.COM 	bcopy(groupName, &iGroupName.name, strlen((char *)groupName));
31959585STim.Szeto@Sun.COM 
31969585STim.Szeto@Sun.COM 	iGroupName.name_size = strlen((char *)groupName);
31979585STim.Szeto@Sun.COM 
31989585STim.Szeto@Sun.COM 	/*
31999585STim.Szeto@Sun.COM 	 * Allocate ioctl input buffer
32009585STim.Szeto@Sun.COM 	 */
32019585STim.Szeto@Sun.COM 	groupListSize = ALLOC_GRP_MEMBER;
32029585STim.Szeto@Sun.COM 	groupListSize = groupListSize * (sizeof (stmf_ge_ident_t));
32039585STim.Szeto@Sun.COM 	iGroupMembers = (stmf_ge_ident_t *)calloc(1, groupListSize);
32049585STim.Szeto@Sun.COM 	if (iGroupMembers == NULL) {
32059585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
32069585STim.Szeto@Sun.COM 		goto done;
32079585STim.Szeto@Sun.COM 	}
32089585STim.Szeto@Sun.COM 
32099585STim.Szeto@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
32109585STim.Szeto@Sun.COM 	/*
32119585STim.Szeto@Sun.COM 	 * Issue ioctl to get the group list
32129585STim.Szeto@Sun.COM 	 */
32139585STim.Szeto@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
32149585STim.Szeto@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&iGroupName;
32159585STim.Szeto@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (stmf_group_name_t);
32169585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf_size = groupListSize;
32179585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupMembers;
32189585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
32199585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
32209585STim.Szeto@Sun.COM 		switch (errno) {
32219585STim.Szeto@Sun.COM 			case EBUSY:
32229585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
32239585STim.Szeto@Sun.COM 				break;
32249585STim.Szeto@Sun.COM 			case EPERM:
32259585STim.Szeto@Sun.COM 			case EACCES:
32269585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
32279585STim.Szeto@Sun.COM 				break;
32289585STim.Szeto@Sun.COM 			default:
32299585STim.Szeto@Sun.COM 				syslog(LOG_DEBUG,
32309585STim.Szeto@Sun.COM 				    "groupListIoctl:ioctl errno(%d)",
32319585STim.Szeto@Sun.COM 				    errno);
32329585STim.Szeto@Sun.COM 				ret = STMF_STATUS_ERROR;
32339585STim.Szeto@Sun.COM 				break;
32349585STim.Szeto@Sun.COM 		}
32359585STim.Szeto@Sun.COM 		goto done;
32369585STim.Szeto@Sun.COM 	}
32379585STim.Szeto@Sun.COM 	/*
32389585STim.Szeto@Sun.COM 	 * Check whether input buffer was large enough
32399585STim.Szeto@Sun.COM 	 */
32409585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_GRP_MEMBER) {
32419585STim.Szeto@Sun.COM 		groupListSize = stmfIoctl.stmf_obuf_max_nentries *
32429585STim.Szeto@Sun.COM 		    sizeof (stmf_ge_ident_t);
32439585STim.Szeto@Sun.COM 		iGroupMembers = realloc(iGroupMembers, groupListSize);
32449585STim.Szeto@Sun.COM 		if (iGroupMembers == NULL) {
32459585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NOMEM;
32469585STim.Szeto@Sun.COM 			goto done;
32479585STim.Szeto@Sun.COM 		}
32489585STim.Szeto@Sun.COM 		stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&iGroupName;
32499585STim.Szeto@Sun.COM 		stmfIoctl.stmf_ibuf_size = sizeof (stmf_group_name_t);
32509585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf_size = groupListSize;
32519585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupMembers;
32529585STim.Szeto@Sun.COM 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
32539585STim.Szeto@Sun.COM 		if (ioctlRet != 0) {
32549585STim.Szeto@Sun.COM 			switch (errno) {
32559585STim.Szeto@Sun.COM 				case EBUSY:
32569585STim.Szeto@Sun.COM 					ret = STMF_ERROR_BUSY;
32579585STim.Szeto@Sun.COM 					break;
32589585STim.Szeto@Sun.COM 				case EPERM:
32599585STim.Szeto@Sun.COM 				case EACCES:
32609585STim.Szeto@Sun.COM 					ret = STMF_ERROR_PERM;
32619585STim.Szeto@Sun.COM 					break;
32629585STim.Szeto@Sun.COM 				default:
32639585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
32649585STim.Szeto@Sun.COM 					    "groupListIoctl:ioctl errno(%d)",
32659585STim.Szeto@Sun.COM 					    errno);
32669585STim.Szeto@Sun.COM 					ret = STMF_STATUS_ERROR;
32679585STim.Szeto@Sun.COM 					break;
32689585STim.Szeto@Sun.COM 			}
32699585STim.Szeto@Sun.COM 			goto done;
32709585STim.Szeto@Sun.COM 		}
32719585STim.Szeto@Sun.COM 	}
32729585STim.Szeto@Sun.COM 
32739585STim.Szeto@Sun.COM 	/* allocate and copy to caller's buffer */
32749585STim.Szeto@Sun.COM 	*groupProps = (stmfGroupProperties *)calloc(1,
327510236SSrivijitha.Dugganapalli@Sun.COM 	    sizeof (stmfGroupProperties) +
327610236SSrivijitha.Dugganapalli@Sun.COM 	    sizeof (stmfDevid) * stmfIoctl.stmf_obuf_nentries);
32779585STim.Szeto@Sun.COM 	if (*groupProps == NULL) {
32789585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
32799585STim.Szeto@Sun.COM 		goto done;
32809585STim.Szeto@Sun.COM 	}
32819585STim.Szeto@Sun.COM 	(*groupProps)->cnt = stmfIoctl.stmf_obuf_nentries;
32829585STim.Szeto@Sun.COM 	for (i = 0; i < stmfIoctl.stmf_obuf_nentries; i++) {
32839585STim.Szeto@Sun.COM 		(*groupProps)->name[i].identLength =
328410113SNattuvetty.Bhavyan@Sun.COM 		    iGroupMembers[i].ident_size;
328510113SNattuvetty.Bhavyan@Sun.COM 		bcopy(iGroupMembers[i].ident, (*groupProps)->name[i].ident,
328610113SNattuvetty.Bhavyan@Sun.COM 		    iGroupMembers[i].ident_size);
32879585STim.Szeto@Sun.COM 	}
32889585STim.Szeto@Sun.COM 
32899585STim.Szeto@Sun.COM done:
32909585STim.Szeto@Sun.COM 	free(iGroupMembers);
32919585STim.Szeto@Sun.COM 	(void) close(fd);
32929585STim.Szeto@Sun.COM 	return (ret);
32939585STim.Szeto@Sun.COM }
32949585STim.Szeto@Sun.COM 
32959585STim.Szeto@Sun.COM /*
32969585STim.Szeto@Sun.COM  * Purpose: access persistent config data for host groups and target groups
32979585STim.Szeto@Sun.COM  */
32989585STim.Szeto@Sun.COM static int
32999585STim.Szeto@Sun.COM iLoadGroupFromPs(stmfGroupList **groupList, int type)
33009585STim.Szeto@Sun.COM {
33019585STim.Szeto@Sun.COM 	int ret;
33029585STim.Szeto@Sun.COM 
33039585STim.Szeto@Sun.COM 	if (groupList == NULL) {
33049585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
33059585STim.Szeto@Sun.COM 	}
33069585STim.Szeto@Sun.COM 
33079585STim.Szeto@Sun.COM 	if (type == HOST_GROUP) {
33089585STim.Szeto@Sun.COM 		ret = psGetHostGroupList(groupList);
33099585STim.Szeto@Sun.COM 	} else if (type == TARGET_GROUP) {
33109585STim.Szeto@Sun.COM 		ret = psGetTargetGroupList(groupList);
33119585STim.Szeto@Sun.COM 	} else {
33129585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
33139585STim.Szeto@Sun.COM 	}
33147836SJohn.Forte@Sun.COM 	switch (ret) {
33157836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
33167836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
33177836SJohn.Forte@Sun.COM 			break;
33187836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
33197836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
33207836SJohn.Forte@Sun.COM 			break;
33217836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
33227836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
33237836SJohn.Forte@Sun.COM 			break;
33247836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
33257836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
33267836SJohn.Forte@Sun.COM 			break;
33277836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
33287836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
33297836SJohn.Forte@Sun.COM 			break;
33307836SJohn.Forte@Sun.COM 		default:
33317836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
33327836SJohn.Forte@Sun.COM 			    "stmfGetHostGroupList:psGetHostGroupList:error(%d)",
33337836SJohn.Forte@Sun.COM 			    ret);
33347836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
33357836SJohn.Forte@Sun.COM 			break;
33367836SJohn.Forte@Sun.COM 	}
33377836SJohn.Forte@Sun.COM 
33387836SJohn.Forte@Sun.COM 	return (ret);
33397836SJohn.Forte@Sun.COM }
33407836SJohn.Forte@Sun.COM 
33417836SJohn.Forte@Sun.COM /*
33429585STim.Szeto@Sun.COM  * stmfGetHostGroupList
33437836SJohn.Forte@Sun.COM  *
33449585STim.Szeto@Sun.COM  * Purpose: Retrieves the list of initiator group oids
33459585STim.Szeto@Sun.COM  *
33469585STim.Szeto@Sun.COM  * hostGroupList - pointer to pointer to hostGroupList structure
33479585STim.Szeto@Sun.COM  *                 on success, this contains the host group list.
33487836SJohn.Forte@Sun.COM  */
33497836SJohn.Forte@Sun.COM int
33509585STim.Szeto@Sun.COM stmfGetHostGroupList(stmfGroupList **hostGroupList)
33519585STim.Szeto@Sun.COM {
33529585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_ERROR;
33539585STim.Szeto@Sun.COM 
33549585STim.Szeto@Sun.COM 	if (hostGroupList == NULL) {
33559585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
33569585STim.Szeto@Sun.COM 	}
33579585STim.Szeto@Sun.COM 
33589585STim.Szeto@Sun.COM 	ret = groupListIoctl(hostGroupList, HOST_GROUP);
33599585STim.Szeto@Sun.COM 	return (ret);
33609585STim.Szeto@Sun.COM }
33619585STim.Szeto@Sun.COM 
33629585STim.Szeto@Sun.COM 
33639585STim.Szeto@Sun.COM /*
33649585STim.Szeto@Sun.COM  * Purpose: access persistent config data for host groups and target groups
33659585STim.Szeto@Sun.COM  */
33669585STim.Szeto@Sun.COM static int
33679585STim.Szeto@Sun.COM iLoadGroupMembersFromPs(stmfGroupName *groupName,
33689585STim.Szeto@Sun.COM     stmfGroupProperties **groupProp, int type)
33697836SJohn.Forte@Sun.COM {
33707836SJohn.Forte@Sun.COM 	int ret;
33717836SJohn.Forte@Sun.COM 
33729585STim.Szeto@Sun.COM 	if (groupName == NULL) {
33737836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
33747836SJohn.Forte@Sun.COM 	}
33757836SJohn.Forte@Sun.COM 
33769585STim.Szeto@Sun.COM 	if (type == HOST_GROUP) {
33779585STim.Szeto@Sun.COM 		ret = psGetHostGroupMemberList((char *)groupName, groupProp);
33789585STim.Szeto@Sun.COM 	} else if (type == TARGET_GROUP) {
33799585STim.Szeto@Sun.COM 		ret = psGetTargetGroupMemberList((char *)groupName, groupProp);
33809585STim.Szeto@Sun.COM 	} else {
33819585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
33829585STim.Szeto@Sun.COM 	}
33837836SJohn.Forte@Sun.COM 	switch (ret) {
33847836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
33857836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
33867836SJohn.Forte@Sun.COM 			break;
33877836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
33887836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
33897836SJohn.Forte@Sun.COM 			break;
33907836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
33917836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
33927836SJohn.Forte@Sun.COM 			break;
33937836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
33947836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
33957836SJohn.Forte@Sun.COM 			break;
33967836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
33977836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
33987836SJohn.Forte@Sun.COM 			break;
33997836SJohn.Forte@Sun.COM 		default:
34007836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
34019585STim.Szeto@Sun.COM 			    "iLoadGroupMembersFromPs:psGetHostGroupList:"
34029585STim.Szeto@Sun.COM 			    "error(%d)", ret);
34037836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
34047836SJohn.Forte@Sun.COM 			break;
34057836SJohn.Forte@Sun.COM 	}
34067836SJohn.Forte@Sun.COM 
34077836SJohn.Forte@Sun.COM 	return (ret);
34087836SJohn.Forte@Sun.COM }
34097836SJohn.Forte@Sun.COM 
34107836SJohn.Forte@Sun.COM /*
34119585STim.Szeto@Sun.COM  * stmfGetHostGroupMembers
34129585STim.Szeto@Sun.COM  *
34139585STim.Szeto@Sun.COM  * Purpose: Retrieves the group properties for a host group
34149585STim.Szeto@Sun.COM  *
34159585STim.Szeto@Sun.COM  * groupName - name of group for which to retrieve host group members.
34169585STim.Szeto@Sun.COM  * groupProp - pointer to pointer to stmfGroupProperties structure
34179585STim.Szeto@Sun.COM  *             on success, this contains the list of group members.
34189585STim.Szeto@Sun.COM  */
34199585STim.Szeto@Sun.COM int
34209585STim.Szeto@Sun.COM stmfGetHostGroupMembers(stmfGroupName *groupName,
34219585STim.Szeto@Sun.COM     stmfGroupProperties **groupProp)
34229585STim.Szeto@Sun.COM {
34239585STim.Szeto@Sun.COM 	int ret;
34249585STim.Szeto@Sun.COM 
34259585STim.Szeto@Sun.COM 	if (groupName == NULL || groupProp == NULL) {
34269585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
34279585STim.Szeto@Sun.COM 	}
34289585STim.Szeto@Sun.COM 
34299585STim.Szeto@Sun.COM 	ret = groupMemberListIoctl(groupName, groupProp, HOST_GROUP);
34309585STim.Szeto@Sun.COM 
34319585STim.Szeto@Sun.COM 	return (ret);
34329585STim.Szeto@Sun.COM }
34339585STim.Szeto@Sun.COM 
34349585STim.Szeto@Sun.COM /*
34357836SJohn.Forte@Sun.COM  * stmfGetProviderData
34367836SJohn.Forte@Sun.COM  *
34377836SJohn.Forte@Sun.COM  * Purpose: Get provider data list
34387836SJohn.Forte@Sun.COM  *
34397836SJohn.Forte@Sun.COM  * providerName - name of provider for which to retrieve the data
34407836SJohn.Forte@Sun.COM  * nvl - pointer to nvlist_t pointer which will contain the nvlist data
34417836SJohn.Forte@Sun.COM  *       retrieved.
34427836SJohn.Forte@Sun.COM  * providerType - type of provider for which to retrieve data.
34437836SJohn.Forte@Sun.COM  *		    STMF_LU_PROVIDER_TYPE
34447836SJohn.Forte@Sun.COM  *		    STMF_PORT_PROVIDER_TYPE
34457836SJohn.Forte@Sun.COM  */
34467836SJohn.Forte@Sun.COM int
34477836SJohn.Forte@Sun.COM stmfGetProviderData(char *providerName, nvlist_t **nvl, int providerType)
34487836SJohn.Forte@Sun.COM {
34497836SJohn.Forte@Sun.COM 	return (stmfGetProviderDataProt(providerName, nvl, providerType,
34507836SJohn.Forte@Sun.COM 	    NULL));
34517836SJohn.Forte@Sun.COM }
34527836SJohn.Forte@Sun.COM 
34537836SJohn.Forte@Sun.COM /*
34547836SJohn.Forte@Sun.COM  * stmfGetProviderDataProt
34557836SJohn.Forte@Sun.COM  *
34567836SJohn.Forte@Sun.COM  * Purpose: Get provider data list with token
34577836SJohn.Forte@Sun.COM  *
34587836SJohn.Forte@Sun.COM  * providerName - name of provider for which to retrieve the data
34597836SJohn.Forte@Sun.COM  * nvl - pointer to nvlist_t pointer which will contain the nvlist data
34607836SJohn.Forte@Sun.COM  *       retrieved.
34617836SJohn.Forte@Sun.COM  * providerType - type of provider for which to retrieve data.
34627836SJohn.Forte@Sun.COM  *		    STMF_LU_PROVIDER_TYPE
34637836SJohn.Forte@Sun.COM  *		    STMF_PORT_PROVIDER_TYPE
34647836SJohn.Forte@Sun.COM  * setToken - Returns the stale data token
34657836SJohn.Forte@Sun.COM  */
34667836SJohn.Forte@Sun.COM int
34677836SJohn.Forte@Sun.COM stmfGetProviderDataProt(char *providerName, nvlist_t **nvl, int providerType,
34687836SJohn.Forte@Sun.COM     uint64_t *setToken)
34697836SJohn.Forte@Sun.COM {
34707836SJohn.Forte@Sun.COM 	int ret;
34717836SJohn.Forte@Sun.COM 
34727836SJohn.Forte@Sun.COM 	if (providerName == NULL || nvl == NULL) {
34737836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
34747836SJohn.Forte@Sun.COM 	}
34757836SJohn.Forte@Sun.COM 	if (providerType != STMF_LU_PROVIDER_TYPE &&
34767836SJohn.Forte@Sun.COM 	    providerType != STMF_PORT_PROVIDER_TYPE) {
34777836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
34787836SJohn.Forte@Sun.COM 	}
34797836SJohn.Forte@Sun.COM 	/* call init */
34807836SJohn.Forte@Sun.COM 	ret = initializeConfig();
34817836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
34827836SJohn.Forte@Sun.COM 		return (ret);
34837836SJohn.Forte@Sun.COM 	}
34849585STim.Szeto@Sun.COM 	return (getProviderData(providerName, nvl, providerType, setToken));
34857836SJohn.Forte@Sun.COM }
34867836SJohn.Forte@Sun.COM 
34877836SJohn.Forte@Sun.COM /*
34887836SJohn.Forte@Sun.COM  * stmfGetProviderDataList
34897836SJohn.Forte@Sun.COM  *
34907836SJohn.Forte@Sun.COM  * Purpose: Get the list of providers currently persisting data
34917836SJohn.Forte@Sun.COM  *
34927836SJohn.Forte@Sun.COM  * providerList - pointer to pointer to an stmfProviderList structure allocated
34937836SJohn.Forte@Sun.COM  *                by the caller. Will contain the list of providers on success.
34947836SJohn.Forte@Sun.COM  */
34957836SJohn.Forte@Sun.COM int
34967836SJohn.Forte@Sun.COM stmfGetProviderDataList(stmfProviderList **providerList)
34977836SJohn.Forte@Sun.COM {
34987836SJohn.Forte@Sun.COM 	int ret;
34997836SJohn.Forte@Sun.COM 
35007836SJohn.Forte@Sun.COM 	ret = psGetProviderDataList(providerList);
35017836SJohn.Forte@Sun.COM 	switch (ret) {
35027836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
35037836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
35047836SJohn.Forte@Sun.COM 			break;
35057836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
35067836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
35077836SJohn.Forte@Sun.COM 			break;
35087836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
35097836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
35107836SJohn.Forte@Sun.COM 			break;
35117836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
35127836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
35137836SJohn.Forte@Sun.COM 			break;
35147836SJohn.Forte@Sun.COM 		default:
35157836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
35167836SJohn.Forte@Sun.COM 			    "stmfGetProviderDataList:psGetProviderDataList"
35177836SJohn.Forte@Sun.COM 			    ":error(%d)", ret);
35187836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
35197836SJohn.Forte@Sun.COM 			break;
35207836SJohn.Forte@Sun.COM 	}
35217836SJohn.Forte@Sun.COM 
35227836SJohn.Forte@Sun.COM 	return (ret);
35237836SJohn.Forte@Sun.COM }
35247836SJohn.Forte@Sun.COM 
35257836SJohn.Forte@Sun.COM 
35267836SJohn.Forte@Sun.COM /*
35277836SJohn.Forte@Sun.COM  * stmfGetSessionList
35287836SJohn.Forte@Sun.COM  *
35297836SJohn.Forte@Sun.COM  * Purpose: Retrieves the session list for a target (devid)
35307836SJohn.Forte@Sun.COM  *
35317836SJohn.Forte@Sun.COM  * devid - devid of target for which to retrieve session information.
35327836SJohn.Forte@Sun.COM  * sessionList - pointer to pointer to stmfSessionList structure
35337836SJohn.Forte@Sun.COM  *             on success, this contains the list of initiator sessions.
35347836SJohn.Forte@Sun.COM  */
35357836SJohn.Forte@Sun.COM int
35367836SJohn.Forte@Sun.COM stmfGetSessionList(stmfDevid *devid, stmfSessionList **sessionList)
35377836SJohn.Forte@Sun.COM {
35387836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
35397836SJohn.Forte@Sun.COM 	int fd;
35407836SJohn.Forte@Sun.COM 	int ioctlRet;
35417836SJohn.Forte@Sun.COM 	int cmd = STMF_IOCTL_SESSION_LIST;
35427836SJohn.Forte@Sun.COM 	int i;
35437836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
354410261SCharles.Ting@Sun.COM 	slist_scsi_session_t *fSessionList, *fSessionListP = NULL;
35457836SJohn.Forte@Sun.COM 	uint8_t ident[260];
35467836SJohn.Forte@Sun.COM 	uint32_t fSessionListSize;
35477836SJohn.Forte@Sun.COM 
35487836SJohn.Forte@Sun.COM 	if (sessionList == NULL || devid == NULL) {
35497836SJohn.Forte@Sun.COM 		ret = STMF_ERROR_INVALID_ARG;
35507836SJohn.Forte@Sun.COM 	}
35517836SJohn.Forte@Sun.COM 
35527836SJohn.Forte@Sun.COM 	/* call init */
35537836SJohn.Forte@Sun.COM 	ret = initializeConfig();
35547836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
35557836SJohn.Forte@Sun.COM 		return (ret);
35567836SJohn.Forte@Sun.COM 	}
35577836SJohn.Forte@Sun.COM 
35587836SJohn.Forte@Sun.COM 	/*
35597836SJohn.Forte@Sun.COM 	 * Open control node for stmf
35607836SJohn.Forte@Sun.COM 	 */
35617836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
35627836SJohn.Forte@Sun.COM 		return (ret);
35637836SJohn.Forte@Sun.COM 
35647836SJohn.Forte@Sun.COM 	/*
35657836SJohn.Forte@Sun.COM 	 * Allocate ioctl input buffer
35667836SJohn.Forte@Sun.COM 	 */
35679585STim.Szeto@Sun.COM 	fSessionListSize = ALLOC_SESSION;
35687836SJohn.Forte@Sun.COM 	fSessionListSize = fSessionListSize * (sizeof (slist_scsi_session_t));
35697836SJohn.Forte@Sun.COM 	fSessionList = (slist_scsi_session_t *)calloc(1, fSessionListSize);
357010261SCharles.Ting@Sun.COM 	fSessionListP = fSessionList;
35717836SJohn.Forte@Sun.COM 	if (fSessionList == NULL) {
357210261SCharles.Ting@Sun.COM 		ret = STMF_ERROR_NOMEM;
357310261SCharles.Ting@Sun.COM 		goto done;
35747836SJohn.Forte@Sun.COM 	}
35757836SJohn.Forte@Sun.COM 
35767836SJohn.Forte@Sun.COM 	ident[IDENT_LENGTH_BYTE] = devid->identLength;
35777836SJohn.Forte@Sun.COM 	bcopy(&(devid->ident), &ident[IDENT_LENGTH_BYTE + 1],
35787836SJohn.Forte@Sun.COM 	    devid->identLength);
35797836SJohn.Forte@Sun.COM 
35807836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
35817836SJohn.Forte@Sun.COM 	/*
35827836SJohn.Forte@Sun.COM 	 * Issue ioctl to get the session list
35837836SJohn.Forte@Sun.COM 	 */
35847836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
35857836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ident;
35867836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (ident);
35877836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = fSessionListSize;
35887836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fSessionList;
35897836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
35907836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
35917836SJohn.Forte@Sun.COM 		switch (errno) {
35927836SJohn.Forte@Sun.COM 			case EBUSY:
35937836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
35947836SJohn.Forte@Sun.COM 				break;
35959585STim.Szeto@Sun.COM 			case EPERM:
35967836SJohn.Forte@Sun.COM 			case EACCES:
35977836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
35987836SJohn.Forte@Sun.COM 				break;
35997836SJohn.Forte@Sun.COM 			default:
36007836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
36017836SJohn.Forte@Sun.COM 				    "stmfGetSessionList:ioctl errno(%d)",
36027836SJohn.Forte@Sun.COM 				    errno);
36037836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
36047836SJohn.Forte@Sun.COM 				break;
36057836SJohn.Forte@Sun.COM 		}
36067836SJohn.Forte@Sun.COM 		goto done;
36077836SJohn.Forte@Sun.COM 	}
36087836SJohn.Forte@Sun.COM 	/*
36097836SJohn.Forte@Sun.COM 	 * Check whether input buffer was large enough
36107836SJohn.Forte@Sun.COM 	 */
36119585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_SESSION) {
36127836SJohn.Forte@Sun.COM 		fSessionListSize = stmfIoctl.stmf_obuf_max_nentries *
36137836SJohn.Forte@Sun.COM 		    sizeof (slist_scsi_session_t);
36147836SJohn.Forte@Sun.COM 		fSessionList = realloc(fSessionList, fSessionListSize);
36157836SJohn.Forte@Sun.COM 		if (fSessionList == NULL) {
361610261SCharles.Ting@Sun.COM 			ret = STMF_ERROR_NOMEM;
361710261SCharles.Ting@Sun.COM 			goto done;
36187836SJohn.Forte@Sun.COM 		}
361910261SCharles.Ting@Sun.COM 		fSessionListP = fSessionList;
36207836SJohn.Forte@Sun.COM 		stmfIoctl.stmf_obuf_size = fSessionListSize;
36217836SJohn.Forte@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fSessionList;
36227836SJohn.Forte@Sun.COM 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
36237836SJohn.Forte@Sun.COM 		if (ioctlRet != 0) {
36247836SJohn.Forte@Sun.COM 			switch (errno) {
36257836SJohn.Forte@Sun.COM 				case EBUSY:
36267836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_BUSY;
36277836SJohn.Forte@Sun.COM 					break;
36289585STim.Szeto@Sun.COM 				case EPERM:
36297836SJohn.Forte@Sun.COM 				case EACCES:
36307836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_PERM;
36317836SJohn.Forte@Sun.COM 					break;
36327836SJohn.Forte@Sun.COM 				default:
36337836SJohn.Forte@Sun.COM 					syslog(LOG_DEBUG,
36347836SJohn.Forte@Sun.COM 					    "stmfGetSessionList:ioctl "
36357836SJohn.Forte@Sun.COM 					    "errno(%d)", errno);
36367836SJohn.Forte@Sun.COM 					ret = STMF_STATUS_ERROR;
36377836SJohn.Forte@Sun.COM 					break;
36387836SJohn.Forte@Sun.COM 			}
36397836SJohn.Forte@Sun.COM 			goto done;
36407836SJohn.Forte@Sun.COM 		}
36417836SJohn.Forte@Sun.COM 	}
36427836SJohn.Forte@Sun.COM 
36437836SJohn.Forte@Sun.COM 	/*
36447836SJohn.Forte@Sun.COM 	 * allocate caller's buffer with the final size
36457836SJohn.Forte@Sun.COM 	 */
36467836SJohn.Forte@Sun.COM 	*sessionList = (stmfSessionList *)calloc(1, sizeof (stmfSessionList) +
36477836SJohn.Forte@Sun.COM 	    stmfIoctl.stmf_obuf_max_nentries * sizeof (stmfSession));
36487836SJohn.Forte@Sun.COM 	if (*sessionList == NULL) {
36497836SJohn.Forte@Sun.COM 		ret = STMF_ERROR_NOMEM;
36507836SJohn.Forte@Sun.COM 		free(sessionList);
36517836SJohn.Forte@Sun.COM 		goto done;
36527836SJohn.Forte@Sun.COM 	}
36537836SJohn.Forte@Sun.COM 
36547836SJohn.Forte@Sun.COM 	(*sessionList)->cnt = stmfIoctl.stmf_obuf_max_nentries;
36557836SJohn.Forte@Sun.COM 
36567836SJohn.Forte@Sun.COM 	/*
36577836SJohn.Forte@Sun.COM 	 * copy session info to caller's buffer
36587836SJohn.Forte@Sun.COM 	 */
36597836SJohn.Forte@Sun.COM 	for (i = 0; i < (*sessionList)->cnt; i++) {
36607836SJohn.Forte@Sun.COM 		(*sessionList)->session[i].initiator.identLength =
36617836SJohn.Forte@Sun.COM 		    fSessionList->initiator[IDENT_LENGTH_BYTE];
36627836SJohn.Forte@Sun.COM 		bcopy(&(fSessionList->initiator[IDENT_LENGTH_BYTE + 1]),
36637836SJohn.Forte@Sun.COM 		    (*sessionList)->session[i].initiator.ident,
36647836SJohn.Forte@Sun.COM 		    STMF_IDENT_LENGTH);
36657836SJohn.Forte@Sun.COM 		bcopy(&(fSessionList->alias),
36667836SJohn.Forte@Sun.COM 		    &((*sessionList)->session[i].alias),
36677836SJohn.Forte@Sun.COM 		    sizeof ((*sessionList)->session[i].alias));
36687836SJohn.Forte@Sun.COM 		bcopy(&(fSessionList++->creation_time),
36697836SJohn.Forte@Sun.COM 		    &((*sessionList)->session[i].creationTime),
36707836SJohn.Forte@Sun.COM 		    sizeof (time_t));
36717836SJohn.Forte@Sun.COM 	}
36727836SJohn.Forte@Sun.COM done:
36737836SJohn.Forte@Sun.COM 	(void) close(fd);
367410261SCharles.Ting@Sun.COM 	free(fSessionListP);
36757836SJohn.Forte@Sun.COM 	return (ret);
36767836SJohn.Forte@Sun.COM }
36777836SJohn.Forte@Sun.COM 
36787836SJohn.Forte@Sun.COM /*
36797836SJohn.Forte@Sun.COM  * stmfGetTargetGroupList
36807836SJohn.Forte@Sun.COM  *
36817836SJohn.Forte@Sun.COM  * Purpose: Retrieves the list of target groups
36827836SJohn.Forte@Sun.COM  *
36837836SJohn.Forte@Sun.COM  * targetGroupList - pointer to a pointer to an stmfGroupList structure. On
36847836SJohn.Forte@Sun.COM  *		     success, it contains the list of target groups.
36857836SJohn.Forte@Sun.COM  */
36867836SJohn.Forte@Sun.COM int
36877836SJohn.Forte@Sun.COM stmfGetTargetGroupList(stmfGroupList **targetGroupList)
36887836SJohn.Forte@Sun.COM {
36897836SJohn.Forte@Sun.COM 	int ret;
36907836SJohn.Forte@Sun.COM 
36917836SJohn.Forte@Sun.COM 	if (targetGroupList == NULL) {
36927836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
36937836SJohn.Forte@Sun.COM 	}
36947836SJohn.Forte@Sun.COM 
36959585STim.Szeto@Sun.COM 	ret = groupListIoctl(targetGroupList, TARGET_GROUP);
36967836SJohn.Forte@Sun.COM 	return (ret);
36977836SJohn.Forte@Sun.COM }
36987836SJohn.Forte@Sun.COM 
36997836SJohn.Forte@Sun.COM /*
37007836SJohn.Forte@Sun.COM  * stmfGetTargetGroupMembers
37017836SJohn.Forte@Sun.COM  *
37027836SJohn.Forte@Sun.COM  * Purpose: Retrieves the group members for a target group
37037836SJohn.Forte@Sun.COM  *
37047836SJohn.Forte@Sun.COM  * groupName - name of target group for which to retrieve members.
37057836SJohn.Forte@Sun.COM  * groupProp - pointer to pointer to stmfGroupProperties structure
37067836SJohn.Forte@Sun.COM  *             on success, this contains the list of group members.
37077836SJohn.Forte@Sun.COM  */
37087836SJohn.Forte@Sun.COM int
37097836SJohn.Forte@Sun.COM stmfGetTargetGroupMembers(stmfGroupName *groupName,
37107836SJohn.Forte@Sun.COM     stmfGroupProperties **groupProp)
37117836SJohn.Forte@Sun.COM {
37127836SJohn.Forte@Sun.COM 	int ret;
37137836SJohn.Forte@Sun.COM 
37147836SJohn.Forte@Sun.COM 	if (groupName == NULL || groupProp == NULL) {
37157836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
37167836SJohn.Forte@Sun.COM 	}
37177836SJohn.Forte@Sun.COM 
37189585STim.Szeto@Sun.COM 	ret = groupMemberListIoctl(groupName, groupProp, TARGET_GROUP);
37197836SJohn.Forte@Sun.COM 
37207836SJohn.Forte@Sun.COM 	return (ret);
37217836SJohn.Forte@Sun.COM }
37227836SJohn.Forte@Sun.COM 
37237836SJohn.Forte@Sun.COM /*
37247836SJohn.Forte@Sun.COM  * stmfGetTargetList
37257836SJohn.Forte@Sun.COM  *
37267836SJohn.Forte@Sun.COM  * Purpose: Retrieves the list of target ports
37277836SJohn.Forte@Sun.COM  *
37287836SJohn.Forte@Sun.COM  * targetList - pointer to a pointer to an stmfDevidList structure.
37297836SJohn.Forte@Sun.COM  *		    On success, it contains the list of local ports (target).
37307836SJohn.Forte@Sun.COM  */
37317836SJohn.Forte@Sun.COM int
37327836SJohn.Forte@Sun.COM stmfGetTargetList(stmfDevidList **targetList)
37337836SJohn.Forte@Sun.COM {
37347836SJohn.Forte@Sun.COM 	int ret;
37357836SJohn.Forte@Sun.COM 	int fd;
37367836SJohn.Forte@Sun.COM 	int ioctlRet;
37377836SJohn.Forte@Sun.COM 	int i;
37387836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
37397836SJohn.Forte@Sun.COM 	/* framework target port list */
37409585STim.Szeto@Sun.COM 	slist_target_port_t *fTargetList, *fTargetListP = NULL;
37417836SJohn.Forte@Sun.COM 	uint32_t fTargetListSize;
37427836SJohn.Forte@Sun.COM 
37437836SJohn.Forte@Sun.COM 	if (targetList == NULL) {
37447836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
37457836SJohn.Forte@Sun.COM 	}
37467836SJohn.Forte@Sun.COM 
37477836SJohn.Forte@Sun.COM 	/* call init */
37487836SJohn.Forte@Sun.COM 	ret = initializeConfig();
37497836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
37507836SJohn.Forte@Sun.COM 		return (ret);
37517836SJohn.Forte@Sun.COM 	}
37527836SJohn.Forte@Sun.COM 
37537836SJohn.Forte@Sun.COM 	/*
37547836SJohn.Forte@Sun.COM 	 * Open control node for stmf
37557836SJohn.Forte@Sun.COM 	 */
37567836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
37577836SJohn.Forte@Sun.COM 		return (ret);
37587836SJohn.Forte@Sun.COM 
37597836SJohn.Forte@Sun.COM 	/*
37607836SJohn.Forte@Sun.COM 	 * Allocate ioctl input buffer
37617836SJohn.Forte@Sun.COM 	 */
37629585STim.Szeto@Sun.COM 	fTargetListSize = ALLOC_TARGET_PORT * sizeof (slist_target_port_t);
37638252SJohn.Forte@Sun.COM 	fTargetListP = fTargetList =
37648252SJohn.Forte@Sun.COM 	    (slist_target_port_t *)calloc(1, fTargetListSize);
37657836SJohn.Forte@Sun.COM 	if (fTargetList == NULL) {
37669585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
37677836SJohn.Forte@Sun.COM 		goto done;
37687836SJohn.Forte@Sun.COM 	}
37697836SJohn.Forte@Sun.COM 
37707836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
37717836SJohn.Forte@Sun.COM 	/*
37728252SJohn.Forte@Sun.COM 	 * Issue ioctl to retrieve target list
37737836SJohn.Forte@Sun.COM 	 */
37747836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
37757836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = fTargetListSize;
37767836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fTargetList;
37777836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_TARGET_PORT_LIST, &stmfIoctl);
37787836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
37797836SJohn.Forte@Sun.COM 		switch (errno) {
37807836SJohn.Forte@Sun.COM 			case EBUSY:
37817836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
37827836SJohn.Forte@Sun.COM 				break;
37839585STim.Szeto@Sun.COM 			case EPERM:
37847836SJohn.Forte@Sun.COM 			case EACCES:
37857836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
37867836SJohn.Forte@Sun.COM 				break;
37877836SJohn.Forte@Sun.COM 			default:
37887836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
37897836SJohn.Forte@Sun.COM 				    "stmfGetTargetList:ioctl errno(%d)", errno);
37907836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
37917836SJohn.Forte@Sun.COM 				break;
37927836SJohn.Forte@Sun.COM 		}
37937836SJohn.Forte@Sun.COM 		goto done;
37947836SJohn.Forte@Sun.COM 	}
37957836SJohn.Forte@Sun.COM 	/*
37967836SJohn.Forte@Sun.COM 	 * Check whether input buffer was large enough
37977836SJohn.Forte@Sun.COM 	 */
37989585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_TARGET_PORT) {
37997836SJohn.Forte@Sun.COM 		fTargetListSize = stmfIoctl.stmf_obuf_max_nentries *
38008116SJohn.Forte@Sun.COM 		    sizeof (slist_target_port_t);
38018252SJohn.Forte@Sun.COM 		fTargetListP = fTargetList =
38028252SJohn.Forte@Sun.COM 		    realloc(fTargetList, fTargetListSize);
38037836SJohn.Forte@Sun.COM 		if (fTargetList == NULL) {
38049585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NOMEM;
38059585STim.Szeto@Sun.COM 			goto done;
38067836SJohn.Forte@Sun.COM 		}
38077836SJohn.Forte@Sun.COM 		stmfIoctl.stmf_obuf_size = fTargetListSize;
38087836SJohn.Forte@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fTargetList;
38097836SJohn.Forte@Sun.COM 		ioctlRet = ioctl(fd, STMF_IOCTL_TARGET_PORT_LIST,
38107836SJohn.Forte@Sun.COM 		    &stmfIoctl);
38117836SJohn.Forte@Sun.COM 		if (ioctlRet != 0) {
38127836SJohn.Forte@Sun.COM 			switch (errno) {
38137836SJohn.Forte@Sun.COM 				case EBUSY:
38147836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_BUSY;
38157836SJohn.Forte@Sun.COM 					break;
38169585STim.Szeto@Sun.COM 				case EPERM:
38177836SJohn.Forte@Sun.COM 				case EACCES:
38187836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_PERM;
38197836SJohn.Forte@Sun.COM 					break;
38207836SJohn.Forte@Sun.COM 				default:
38217836SJohn.Forte@Sun.COM 					syslog(LOG_DEBUG,
38227836SJohn.Forte@Sun.COM 					    "stmfGetTargetList:ioctl errno(%d)",
38237836SJohn.Forte@Sun.COM 					    errno);
38247836SJohn.Forte@Sun.COM 					ret = STMF_STATUS_ERROR;
38257836SJohn.Forte@Sun.COM 					break;
38267836SJohn.Forte@Sun.COM 			}
38277836SJohn.Forte@Sun.COM 			goto done;
38287836SJohn.Forte@Sun.COM 		}
38297836SJohn.Forte@Sun.COM 	}
38307836SJohn.Forte@Sun.COM 
38317836SJohn.Forte@Sun.COM 	*targetList = (stmfDevidList *)calloc(1,
38327836SJohn.Forte@Sun.COM 	    stmfIoctl.stmf_obuf_max_nentries * sizeof (stmfDevid) +
38337836SJohn.Forte@Sun.COM 	    sizeof (stmfDevidList));
38349585STim.Szeto@Sun.COM 	if (*targetList == NULL) {
38359585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
38369585STim.Szeto@Sun.COM 		goto done;
38379585STim.Szeto@Sun.COM 	}
38387836SJohn.Forte@Sun.COM 
38397836SJohn.Forte@Sun.COM 	(*targetList)->cnt = stmfIoctl.stmf_obuf_max_nentries;
38407836SJohn.Forte@Sun.COM 	for (i = 0; i < stmfIoctl.stmf_obuf_max_nentries; i++, fTargetList++) {
38417836SJohn.Forte@Sun.COM 		(*targetList)->devid[i].identLength =
38427836SJohn.Forte@Sun.COM 		    fTargetList->target[IDENT_LENGTH_BYTE];
38437836SJohn.Forte@Sun.COM 		bcopy(&fTargetList->target[IDENT_LENGTH_BYTE + 1],
38447836SJohn.Forte@Sun.COM 		    &(*targetList)->devid[i].ident,
38457836SJohn.Forte@Sun.COM 		    fTargetList->target[IDENT_LENGTH_BYTE]);
38467836SJohn.Forte@Sun.COM 	}
38477836SJohn.Forte@Sun.COM 
38487836SJohn.Forte@Sun.COM done:
38497836SJohn.Forte@Sun.COM 	(void) close(fd);
38508252SJohn.Forte@Sun.COM 	free(fTargetListP);
38517836SJohn.Forte@Sun.COM 	return (ret);
38527836SJohn.Forte@Sun.COM }
38537836SJohn.Forte@Sun.COM 
38547836SJohn.Forte@Sun.COM /*
38557836SJohn.Forte@Sun.COM  * stmfGetTargetProperties
38567836SJohn.Forte@Sun.COM  *
38577836SJohn.Forte@Sun.COM  * Purpose:  Retrieves the properties for a logical unit
38587836SJohn.Forte@Sun.COM  *
38597836SJohn.Forte@Sun.COM  * devid - devid of the target for which to retrieve properties
38607836SJohn.Forte@Sun.COM  * targetProps - pointer to an stmfTargetProperties structure.
38617836SJohn.Forte@Sun.COM  *		On success, it contains the target properties for
38627836SJohn.Forte@Sun.COM  *		the specified devid.
38637836SJohn.Forte@Sun.COM  */
38647836SJohn.Forte@Sun.COM int
38657836SJohn.Forte@Sun.COM stmfGetTargetProperties(stmfDevid *devid, stmfTargetProperties *targetProps)
38667836SJohn.Forte@Sun.COM {
38677836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
38687836SJohn.Forte@Sun.COM 	int fd;
38697836SJohn.Forte@Sun.COM 	int ioctlRet;
38707836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
38717836SJohn.Forte@Sun.COM 	sioc_target_port_props_t targetProperties;
38727836SJohn.Forte@Sun.COM 
38737836SJohn.Forte@Sun.COM 	if (devid == NULL || targetProps == NULL) {
38747836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
38757836SJohn.Forte@Sun.COM 	}
38767836SJohn.Forte@Sun.COM 
38777836SJohn.Forte@Sun.COM 	/* call init */
38787836SJohn.Forte@Sun.COM 	ret = initializeConfig();
38797836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
38807836SJohn.Forte@Sun.COM 		return (ret);
38817836SJohn.Forte@Sun.COM 	}
38827836SJohn.Forte@Sun.COM 
38837836SJohn.Forte@Sun.COM 	/*
38847836SJohn.Forte@Sun.COM 	 * Open control node for stmf
38857836SJohn.Forte@Sun.COM 	 */
38867836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
38877836SJohn.Forte@Sun.COM 		return (ret);
38887836SJohn.Forte@Sun.COM 
38897836SJohn.Forte@Sun.COM 	targetProperties.tgt_id[IDENT_LENGTH_BYTE] = devid->identLength;
38907836SJohn.Forte@Sun.COM 	bcopy(&(devid->ident), &targetProperties.tgt_id[IDENT_LENGTH_BYTE + 1],
38917836SJohn.Forte@Sun.COM 	    devid->identLength);
38927836SJohn.Forte@Sun.COM 
38937836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
38947836SJohn.Forte@Sun.COM 	/*
38957836SJohn.Forte@Sun.COM 	 * Issue ioctl to add to the host group
38967836SJohn.Forte@Sun.COM 	 */
38977836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
38987836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (targetProperties.tgt_id);
38997836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&targetProperties.tgt_id;
39007836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&targetProperties;
39017836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = sizeof (targetProperties);
39027836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_GET_TARGET_PORT_PROPERTIES,
39037836SJohn.Forte@Sun.COM 	    &stmfIoctl);
39047836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
39057836SJohn.Forte@Sun.COM 		switch (errno) {
39067836SJohn.Forte@Sun.COM 			case EBUSY:
39077836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
39087836SJohn.Forte@Sun.COM 				break;
39099585STim.Szeto@Sun.COM 			case EPERM:
39107836SJohn.Forte@Sun.COM 			case EACCES:
39117836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
39127836SJohn.Forte@Sun.COM 				break;
39137836SJohn.Forte@Sun.COM 			case ENOENT:
39147836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
39157836SJohn.Forte@Sun.COM 				break;
39167836SJohn.Forte@Sun.COM 			default:
39177836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
39187836SJohn.Forte@Sun.COM 				    "stmfGetTargetProperties:ioctl errno(%d)",
39197836SJohn.Forte@Sun.COM 				    errno);
39207836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
39217836SJohn.Forte@Sun.COM 				break;
39227836SJohn.Forte@Sun.COM 		}
39237836SJohn.Forte@Sun.COM 		goto done;
39247836SJohn.Forte@Sun.COM 	}
39257836SJohn.Forte@Sun.COM 
39267836SJohn.Forte@Sun.COM 	bcopy(targetProperties.tgt_provider_name, targetProps->providerName,
39277836SJohn.Forte@Sun.COM 	    sizeof (targetProperties.tgt_provider_name));
39287836SJohn.Forte@Sun.COM 	if (targetProperties.tgt_state == STMF_STATE_ONLINE) {
39297836SJohn.Forte@Sun.COM 		targetProps->status = STMF_TARGET_PORT_ONLINE;
39307836SJohn.Forte@Sun.COM 	} else if (targetProperties.tgt_state == STMF_STATE_OFFLINE) {
39317836SJohn.Forte@Sun.COM 		targetProps->status = STMF_TARGET_PORT_OFFLINE;
39327836SJohn.Forte@Sun.COM 	} else if (targetProperties.tgt_state == STMF_STATE_ONLINING) {
39337836SJohn.Forte@Sun.COM 		targetProps->status = STMF_TARGET_PORT_ONLINING;
39347836SJohn.Forte@Sun.COM 	} else if (targetProperties.tgt_state == STMF_STATE_OFFLINING) {
39357836SJohn.Forte@Sun.COM 		targetProps->status = STMF_TARGET_PORT_OFFLINING;
39367836SJohn.Forte@Sun.COM 	}
39377836SJohn.Forte@Sun.COM 	bcopy(targetProperties.tgt_alias, targetProps->alias,
39387836SJohn.Forte@Sun.COM 	    sizeof (targetProps->alias));
39397836SJohn.Forte@Sun.COM done:
39407836SJohn.Forte@Sun.COM 	(void) close(fd);
39417836SJohn.Forte@Sun.COM 	return (ret);
39427836SJohn.Forte@Sun.COM }
39437836SJohn.Forte@Sun.COM 
39447836SJohn.Forte@Sun.COM /*
39457836SJohn.Forte@Sun.COM  * stmfGetLogicalUnitList
39467836SJohn.Forte@Sun.COM  *
39477836SJohn.Forte@Sun.COM  * Purpose: Retrieves list of logical unit Object IDs
39487836SJohn.Forte@Sun.COM  *
39497836SJohn.Forte@Sun.COM  * luList - pointer to a pointer to a stmfGuidList structure. On success,
39507836SJohn.Forte@Sun.COM  *          it contains the list of logical unit guids.
39517836SJohn.Forte@Sun.COM  *
39527836SJohn.Forte@Sun.COM  */
39537836SJohn.Forte@Sun.COM int
39547836SJohn.Forte@Sun.COM stmfGetLogicalUnitList(stmfGuidList **luList)
39557836SJohn.Forte@Sun.COM {
39567836SJohn.Forte@Sun.COM 	int ret;
39577836SJohn.Forte@Sun.COM 	int fd;
39587836SJohn.Forte@Sun.COM 	int ioctlRet;
39597836SJohn.Forte@Sun.COM 	int cmd = STMF_IOCTL_LU_LIST;
39609585STim.Szeto@Sun.COM 	int i;
39617836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
39627836SJohn.Forte@Sun.COM 	slist_lu_t *fLuList;
39637836SJohn.Forte@Sun.COM 	uint32_t fLuListSize;
39649585STim.Szeto@Sun.COM 	uint32_t listCnt;
39657836SJohn.Forte@Sun.COM 
39667836SJohn.Forte@Sun.COM 	if (luList == NULL) {
39677836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
39687836SJohn.Forte@Sun.COM 	}
39697836SJohn.Forte@Sun.COM 
39707836SJohn.Forte@Sun.COM 	/* call init */
39717836SJohn.Forte@Sun.COM 	ret = initializeConfig();
39727836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
39737836SJohn.Forte@Sun.COM 		return (ret);
39747836SJohn.Forte@Sun.COM 	}
39757836SJohn.Forte@Sun.COM 
39767836SJohn.Forte@Sun.COM 	/*
39777836SJohn.Forte@Sun.COM 	 * Open control node for stmf
39787836SJohn.Forte@Sun.COM 	 */
39797836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
39807836SJohn.Forte@Sun.COM 		return (ret);
39817836SJohn.Forte@Sun.COM 
39827836SJohn.Forte@Sun.COM 	/*
39837836SJohn.Forte@Sun.COM 	 * Allocate ioctl input buffer
39847836SJohn.Forte@Sun.COM 	 */
39859585STim.Szeto@Sun.COM 	fLuListSize = ALLOC_LU;
39867836SJohn.Forte@Sun.COM 	fLuListSize = fLuListSize * (sizeof (slist_lu_t));
39877836SJohn.Forte@Sun.COM 	fLuList = (slist_lu_t *)calloc(1, fLuListSize);
39887836SJohn.Forte@Sun.COM 	if (fLuList == NULL) {
39899585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
39909585STim.Szeto@Sun.COM 		goto done;
39917836SJohn.Forte@Sun.COM 	}
39927836SJohn.Forte@Sun.COM 
39937836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
39947836SJohn.Forte@Sun.COM 	/*
39957836SJohn.Forte@Sun.COM 	 * Issue ioctl to get the LU list
39967836SJohn.Forte@Sun.COM 	 */
39977836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
39987836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = fLuListSize;
39997836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fLuList;
40007836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
40017836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
40027836SJohn.Forte@Sun.COM 		switch (errno) {
40037836SJohn.Forte@Sun.COM 			case EBUSY:
40047836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
40057836SJohn.Forte@Sun.COM 				break;
40069585STim.Szeto@Sun.COM 			case EPERM:
40077836SJohn.Forte@Sun.COM 			case EACCES:
40087836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
40097836SJohn.Forte@Sun.COM 				break;
40107836SJohn.Forte@Sun.COM 			default:
40117836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
40127836SJohn.Forte@Sun.COM 				    "stmfGetLogicalUnitList:ioctl errno(%d)",
40137836SJohn.Forte@Sun.COM 				    errno);
40147836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
40157836SJohn.Forte@Sun.COM 				break;
40167836SJohn.Forte@Sun.COM 		}
40177836SJohn.Forte@Sun.COM 		goto done;
40187836SJohn.Forte@Sun.COM 	}
40197836SJohn.Forte@Sun.COM 	/*
40207836SJohn.Forte@Sun.COM 	 * Check whether input buffer was large enough
40217836SJohn.Forte@Sun.COM 	 */
40229585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_LU) {
40237836SJohn.Forte@Sun.COM 		fLuListSize = stmfIoctl.stmf_obuf_max_nentries *
40247836SJohn.Forte@Sun.COM 		    sizeof (slist_lu_t);
40259585STim.Szeto@Sun.COM 		free(fLuList);
40269585STim.Szeto@Sun.COM 		fLuList = (slist_lu_t *)calloc(1, fLuListSize);
40277836SJohn.Forte@Sun.COM 		if (fLuList == NULL) {
40289585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NOMEM;
40299585STim.Szeto@Sun.COM 			goto done;
40307836SJohn.Forte@Sun.COM 		}
40317836SJohn.Forte@Sun.COM 		stmfIoctl.stmf_obuf_size = fLuListSize;
40327836SJohn.Forte@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fLuList;
40337836SJohn.Forte@Sun.COM 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
40347836SJohn.Forte@Sun.COM 		if (ioctlRet != 0) {
40357836SJohn.Forte@Sun.COM 			switch (errno) {
40367836SJohn.Forte@Sun.COM 				case EBUSY:
40377836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_BUSY;
40387836SJohn.Forte@Sun.COM 					break;
40399585STim.Szeto@Sun.COM 				case EPERM:
40407836SJohn.Forte@Sun.COM 				case EACCES:
40417836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_PERM;
40427836SJohn.Forte@Sun.COM 					break;
40437836SJohn.Forte@Sun.COM 				default:
40447836SJohn.Forte@Sun.COM 					syslog(LOG_DEBUG,
40457836SJohn.Forte@Sun.COM 					    "stmfGetLogicalUnitList:"
40467836SJohn.Forte@Sun.COM 					    "ioctl errno(%d)", errno);
40477836SJohn.Forte@Sun.COM 					ret = STMF_STATUS_ERROR;
40487836SJohn.Forte@Sun.COM 					break;
40497836SJohn.Forte@Sun.COM 			}
40507836SJohn.Forte@Sun.COM 			goto done;
40517836SJohn.Forte@Sun.COM 		}
40527836SJohn.Forte@Sun.COM 	}
40537836SJohn.Forte@Sun.COM 
40547836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
40557836SJohn.Forte@Sun.COM 		goto done;
40567836SJohn.Forte@Sun.COM 	}
40577836SJohn.Forte@Sun.COM 
40589585STim.Szeto@Sun.COM 	listCnt = stmfIoctl.stmf_obuf_nentries;
40597836SJohn.Forte@Sun.COM 
40607836SJohn.Forte@Sun.COM 	/*
40617836SJohn.Forte@Sun.COM 	 * allocate caller's buffer with the final size
40627836SJohn.Forte@Sun.COM 	 */
40637836SJohn.Forte@Sun.COM 	*luList = (stmfGuidList *)calloc(1, sizeof (stmfGuidList) +
40649585STim.Szeto@Sun.COM 	    listCnt * sizeof (stmfGuid));
40657836SJohn.Forte@Sun.COM 	if (*luList == NULL) {
40667836SJohn.Forte@Sun.COM 		ret = STMF_ERROR_NOMEM;
40677836SJohn.Forte@Sun.COM 		goto done;
40687836SJohn.Forte@Sun.COM 	}
40697836SJohn.Forte@Sun.COM 
40709585STim.Szeto@Sun.COM 	(*luList)->cnt = listCnt;
40719585STim.Szeto@Sun.COM 
40729585STim.Szeto@Sun.COM 	/* copy to caller's buffer */
40739585STim.Szeto@Sun.COM 	for (i = 0; i < listCnt; i++) {
40749585STim.Szeto@Sun.COM 		bcopy(&fLuList[i].lu_guid, (*luList)->guid[i].guid,
40759585STim.Szeto@Sun.COM 		    sizeof (stmfGuid));
40769585STim.Szeto@Sun.COM 	}
40779585STim.Szeto@Sun.COM 
40787836SJohn.Forte@Sun.COM 	/*
40799585STim.Szeto@Sun.COM 	 * sort the list. This gives a consistent view across gets
40807836SJohn.Forte@Sun.COM 	 */
40819585STim.Szeto@Sun.COM 	qsort((void *)&((*luList)->guid[0]), (*luList)->cnt,
40829585STim.Szeto@Sun.COM 	    sizeof (stmfGuid), guidCompare);
40837836SJohn.Forte@Sun.COM 
40847836SJohn.Forte@Sun.COM done:
40857836SJohn.Forte@Sun.COM 	(void) close(fd);
40867836SJohn.Forte@Sun.COM 	/*
40877836SJohn.Forte@Sun.COM 	 * free internal buffers
40887836SJohn.Forte@Sun.COM 	 */
40897836SJohn.Forte@Sun.COM 	free(fLuList);
40907836SJohn.Forte@Sun.COM 	return (ret);
40917836SJohn.Forte@Sun.COM }
40927836SJohn.Forte@Sun.COM 
40937836SJohn.Forte@Sun.COM /*
40947836SJohn.Forte@Sun.COM  * stmfGetLogicalUnitProperties
40957836SJohn.Forte@Sun.COM  *
40967836SJohn.Forte@Sun.COM  * Purpose:  Retrieves the properties for a logical unit
40977836SJohn.Forte@Sun.COM  *
40987836SJohn.Forte@Sun.COM  * lu - guid of the logical unit for which to retrieve properties
40997836SJohn.Forte@Sun.COM  * stmfLuProps - pointer to an stmfLogicalUnitProperties structure. On success,
41007836SJohn.Forte@Sun.COM  *               it contains the logical unit properties for the specified guid.
41017836SJohn.Forte@Sun.COM  */
41027836SJohn.Forte@Sun.COM int
41037836SJohn.Forte@Sun.COM stmfGetLogicalUnitProperties(stmfGuid *lu, stmfLogicalUnitProperties *luProps)
41047836SJohn.Forte@Sun.COM {
41057836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
41067836SJohn.Forte@Sun.COM 	int stmfRet;
41077836SJohn.Forte@Sun.COM 	int fd;
41087836SJohn.Forte@Sun.COM 	int ioctlRet;
41097836SJohn.Forte@Sun.COM 	int cmd = STMF_IOCTL_GET_LU_PROPERTIES;
41107836SJohn.Forte@Sun.COM 	stmfViewEntryList *viewEntryList = NULL;
41117836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
41127836SJohn.Forte@Sun.COM 	sioc_lu_props_t fLuProps;
41137836SJohn.Forte@Sun.COM 
41149585STim.Szeto@Sun.COM 	if (lu == NULL || luProps == NULL) {
41159585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
41167836SJohn.Forte@Sun.COM 	}
41177836SJohn.Forte@Sun.COM 
41187836SJohn.Forte@Sun.COM 	bzero(luProps, sizeof (stmfLogicalUnitProperties));
41197836SJohn.Forte@Sun.COM 
41207836SJohn.Forte@Sun.COM 	/* call init */
41217836SJohn.Forte@Sun.COM 	ret = initializeConfig();
41227836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
41237836SJohn.Forte@Sun.COM 		return (ret);
41247836SJohn.Forte@Sun.COM 	}
41257836SJohn.Forte@Sun.COM 
41267836SJohn.Forte@Sun.COM 	/*
41277836SJohn.Forte@Sun.COM 	 * Open control node for stmf
41287836SJohn.Forte@Sun.COM 	 */
41297836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
41307836SJohn.Forte@Sun.COM 		return (ret);
41317836SJohn.Forte@Sun.COM 
41327836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
41337836SJohn.Forte@Sun.COM 	/*
41347836SJohn.Forte@Sun.COM 	 * Issue ioctl to add to the host group
41357836SJohn.Forte@Sun.COM 	 */
41367836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
41377836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (stmfGuid);
41387836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)lu;
41397836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&fLuProps;
41407836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = sizeof (fLuProps);
41417836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
41427836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
41437836SJohn.Forte@Sun.COM 		switch (errno) {
41447836SJohn.Forte@Sun.COM 			case EBUSY:
41457836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
41467836SJohn.Forte@Sun.COM 				break;
41479585STim.Szeto@Sun.COM 			case EPERM:
41487836SJohn.Forte@Sun.COM 			case EACCES:
41497836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
41507836SJohn.Forte@Sun.COM 				break;
41517836SJohn.Forte@Sun.COM 			case ENOENT:
41527836SJohn.Forte@Sun.COM 				stmfRet = stmfGetViewEntryList(lu,
41537836SJohn.Forte@Sun.COM 				    &viewEntryList);
41547836SJohn.Forte@Sun.COM 				if (stmfRet == STMF_STATUS_SUCCESS) {
41557836SJohn.Forte@Sun.COM 					luProps->status =
41567836SJohn.Forte@Sun.COM 					    STMF_LOGICAL_UNIT_UNREGISTERED;
41577836SJohn.Forte@Sun.COM 					if (viewEntryList->cnt > 0) {
41587836SJohn.Forte@Sun.COM 						ret = STMF_STATUS_SUCCESS;
41597836SJohn.Forte@Sun.COM 					} else {
41607836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_NOT_FOUND;
41617836SJohn.Forte@Sun.COM 					}
41627836SJohn.Forte@Sun.COM 				} else {
41637836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_NOT_FOUND;
41647836SJohn.Forte@Sun.COM 				}
41657836SJohn.Forte@Sun.COM 				stmfFreeMemory(viewEntryList);
41667836SJohn.Forte@Sun.COM 				break;
41677836SJohn.Forte@Sun.COM 			default:
41687836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
41697836SJohn.Forte@Sun.COM 				    "stmfGetLogicalUnit:ioctl errno(%d)",
41707836SJohn.Forte@Sun.COM 				    errno);
41717836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
41727836SJohn.Forte@Sun.COM 				break;
41737836SJohn.Forte@Sun.COM 		}
41747836SJohn.Forte@Sun.COM 		goto done;
41757836SJohn.Forte@Sun.COM 	}
41767836SJohn.Forte@Sun.COM 
41777836SJohn.Forte@Sun.COM 	bcopy(fLuProps.lu_provider_name, luProps->providerName,
41787836SJohn.Forte@Sun.COM 	    sizeof (fLuProps.lu_provider_name));
41797836SJohn.Forte@Sun.COM 	if (fLuProps.lu_state == STMF_STATE_ONLINE) {
41807836SJohn.Forte@Sun.COM 		luProps->status = STMF_LOGICAL_UNIT_ONLINE;
41817836SJohn.Forte@Sun.COM 	} else if (fLuProps.lu_state == STMF_STATE_OFFLINE) {
41827836SJohn.Forte@Sun.COM 		luProps->status = STMF_LOGICAL_UNIT_OFFLINE;
41837836SJohn.Forte@Sun.COM 	} else if (fLuProps.lu_state == STMF_STATE_ONLINING) {
41847836SJohn.Forte@Sun.COM 		luProps->status = STMF_LOGICAL_UNIT_ONLINING;
41857836SJohn.Forte@Sun.COM 	} else if (fLuProps.lu_state == STMF_STATE_OFFLINING) {
41867836SJohn.Forte@Sun.COM 		luProps->status = STMF_LOGICAL_UNIT_OFFLINING;
41877836SJohn.Forte@Sun.COM 	}
41887836SJohn.Forte@Sun.COM 	bcopy(fLuProps.lu_alias, luProps->alias, sizeof (luProps->alias));
41897836SJohn.Forte@Sun.COM done:
41907836SJohn.Forte@Sun.COM 	(void) close(fd);
41917836SJohn.Forte@Sun.COM 	return (ret);
41927836SJohn.Forte@Sun.COM }
41937836SJohn.Forte@Sun.COM 
41947836SJohn.Forte@Sun.COM /*
41957836SJohn.Forte@Sun.COM  * stmfGetState
41967836SJohn.Forte@Sun.COM  *
41977836SJohn.Forte@Sun.COM  * Purpose: retrieve the current state of the stmf module
41987836SJohn.Forte@Sun.COM  *
41997836SJohn.Forte@Sun.COM  * state - pointer to stmfState structure allocated by the caller
42007836SJohn.Forte@Sun.COM  *         On success, contains the state of stmf
42017836SJohn.Forte@Sun.COM  */
42027836SJohn.Forte@Sun.COM int
42037836SJohn.Forte@Sun.COM stmfGetState(stmfState *state)
42047836SJohn.Forte@Sun.COM {
42057836SJohn.Forte@Sun.COM 	int ret;
42067836SJohn.Forte@Sun.COM 	stmf_state_desc_t iState;
42077836SJohn.Forte@Sun.COM 
42087836SJohn.Forte@Sun.COM 	if (state == NULL) {
42097836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
42107836SJohn.Forte@Sun.COM 	}
42117836SJohn.Forte@Sun.COM 
42127836SJohn.Forte@Sun.COM 	ret = getStmfState(&iState);
42137836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
42147836SJohn.Forte@Sun.COM 		return (ret);
42157836SJohn.Forte@Sun.COM 	}
42167836SJohn.Forte@Sun.COM 	switch (iState.state) {
42177836SJohn.Forte@Sun.COM 		case STMF_STATE_ONLINE:
42187836SJohn.Forte@Sun.COM 			state->operationalState =
42197836SJohn.Forte@Sun.COM 			    STMF_SERVICE_STATE_ONLINE;
42207836SJohn.Forte@Sun.COM 			break;
42217836SJohn.Forte@Sun.COM 		case STMF_STATE_OFFLINE:
42227836SJohn.Forte@Sun.COM 			state->operationalState =
42237836SJohn.Forte@Sun.COM 			    STMF_SERVICE_STATE_OFFLINE;
42247836SJohn.Forte@Sun.COM 			break;
42257836SJohn.Forte@Sun.COM 		case STMF_STATE_ONLINING:
42267836SJohn.Forte@Sun.COM 			state->operationalState =
42277836SJohn.Forte@Sun.COM 			    STMF_SERVICE_STATE_ONLINING;
42287836SJohn.Forte@Sun.COM 			break;
42297836SJohn.Forte@Sun.COM 		case STMF_STATE_OFFLINING:
42307836SJohn.Forte@Sun.COM 			state->operationalState =
42317836SJohn.Forte@Sun.COM 			    STMF_SERVICE_STATE_OFFLINING;
42327836SJohn.Forte@Sun.COM 			break;
42337836SJohn.Forte@Sun.COM 		default:
42347836SJohn.Forte@Sun.COM 			state->operationalState =
42357836SJohn.Forte@Sun.COM 			    STMF_SERVICE_STATE_UNKNOWN;
42367836SJohn.Forte@Sun.COM 			break;
42377836SJohn.Forte@Sun.COM 	}
42387836SJohn.Forte@Sun.COM 	switch (iState.config_state) {
42397836SJohn.Forte@Sun.COM 		case STMF_CONFIG_NONE:
42407836SJohn.Forte@Sun.COM 			state->configState = STMF_CONFIG_STATE_NONE;
42417836SJohn.Forte@Sun.COM 			break;
42427836SJohn.Forte@Sun.COM 		case STMF_CONFIG_INIT:
42437836SJohn.Forte@Sun.COM 			state->configState = STMF_CONFIG_STATE_INIT;
42447836SJohn.Forte@Sun.COM 			break;
42457836SJohn.Forte@Sun.COM 		case STMF_CONFIG_INIT_DONE:
42467836SJohn.Forte@Sun.COM 			state->configState =
42477836SJohn.Forte@Sun.COM 			    STMF_CONFIG_STATE_INIT_DONE;
42487836SJohn.Forte@Sun.COM 			break;
42497836SJohn.Forte@Sun.COM 		default:
42507836SJohn.Forte@Sun.COM 			state->configState =
42517836SJohn.Forte@Sun.COM 			    STMF_CONFIG_STATE_UNKNOWN;
42527836SJohn.Forte@Sun.COM 			break;
42537836SJohn.Forte@Sun.COM 	}
42547836SJohn.Forte@Sun.COM 	return (STMF_STATUS_SUCCESS);
42557836SJohn.Forte@Sun.COM }
42567836SJohn.Forte@Sun.COM 
42577836SJohn.Forte@Sun.COM /*
42587836SJohn.Forte@Sun.COM  * stmfGetViewEntryList
42597836SJohn.Forte@Sun.COM  *
42607836SJohn.Forte@Sun.COM  * Purpose: Retrieves the list of view entries for the specified
42617836SJohn.Forte@Sun.COM  *          logical unit.
42627836SJohn.Forte@Sun.COM  *
42637836SJohn.Forte@Sun.COM  * lu - the guid of the logical unit for which to retrieve the view entry list
42647836SJohn.Forte@Sun.COM  * viewEntryList - a pointer to a pointer to a stmfViewEntryList structure. On
42657836SJohn.Forte@Sun.COM  *                 success, contains the list of view entries.
42667836SJohn.Forte@Sun.COM  */
42677836SJohn.Forte@Sun.COM int
42687836SJohn.Forte@Sun.COM stmfGetViewEntryList(stmfGuid *lu, stmfViewEntryList **viewEntryList)
42697836SJohn.Forte@Sun.COM {
42707836SJohn.Forte@Sun.COM 	int ret;
42719585STim.Szeto@Sun.COM 	int fd;
42729585STim.Szeto@Sun.COM 	int ioctlRet;
42739585STim.Szeto@Sun.COM 	int cmd = STMF_IOCTL_LU_VE_LIST;
42749585STim.Szeto@Sun.COM 	int i;
42759585STim.Szeto@Sun.COM 	stmf_iocdata_t stmfIoctl;
42769585STim.Szeto@Sun.COM 	stmf_view_op_entry_t *fVeList;
42779585STim.Szeto@Sun.COM 	uint32_t fVeListSize;
42789585STim.Szeto@Sun.COM 	uint32_t listCnt;
42797836SJohn.Forte@Sun.COM 
42807836SJohn.Forte@Sun.COM 	if (lu == NULL || viewEntryList == NULL) {
42817836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
42827836SJohn.Forte@Sun.COM 	}
42837836SJohn.Forte@Sun.COM 
42849585STim.Szeto@Sun.COM 	/* call init */
42859585STim.Szeto@Sun.COM 	ret = initializeConfig();
42869585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
42879585STim.Szeto@Sun.COM 		return (ret);
42889585STim.Szeto@Sun.COM 	}
42899585STim.Szeto@Sun.COM 
42909585STim.Szeto@Sun.COM 	/*
42919585STim.Szeto@Sun.COM 	 * Open control node for stmf
42929585STim.Szeto@Sun.COM 	 */
42939585STim.Szeto@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
42949585STim.Szeto@Sun.COM 		return (ret);
42959585STim.Szeto@Sun.COM 
42969585STim.Szeto@Sun.COM 	/*
42979585STim.Szeto@Sun.COM 	 * Allocate ioctl input buffer
42989585STim.Szeto@Sun.COM 	 */
42999585STim.Szeto@Sun.COM 	fVeListSize = ALLOC_VE;
43009585STim.Szeto@Sun.COM 	fVeListSize = fVeListSize * (sizeof (stmf_view_op_entry_t));
43019585STim.Szeto@Sun.COM 	fVeList = (stmf_view_op_entry_t *)calloc(1, fVeListSize);
43029585STim.Szeto@Sun.COM 	if (fVeList == NULL) {
43039585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
43049585STim.Szeto@Sun.COM 		goto done;
43059585STim.Szeto@Sun.COM 	}
43069585STim.Szeto@Sun.COM 
43079585STim.Szeto@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
43089585STim.Szeto@Sun.COM 	/*
43099585STim.Szeto@Sun.COM 	 * Issue ioctl to get the LU list
43109585STim.Szeto@Sun.COM 	 */
43119585STim.Szeto@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
43129585STim.Szeto@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)lu;
43139585STim.Szeto@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (stmfGuid);
43149585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf_size = fVeListSize;
43159585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fVeList;
43169585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
43179585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
43189585STim.Szeto@Sun.COM 		switch (errno) {
43199585STim.Szeto@Sun.COM 			case EBUSY:
43209585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
43219585STim.Szeto@Sun.COM 				break;
43229585STim.Szeto@Sun.COM 			case EPERM:
43239585STim.Szeto@Sun.COM 			case EACCES:
43249585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
43259585STim.Szeto@Sun.COM 				break;
43269585STim.Szeto@Sun.COM 			default:
43279585STim.Szeto@Sun.COM 				syslog(LOG_DEBUG,
43289585STim.Szeto@Sun.COM 				    "stmfGetViewEntryList:ioctl errno(%d)",
43299585STim.Szeto@Sun.COM 				    errno);
43309585STim.Szeto@Sun.COM 				ret = STMF_STATUS_ERROR;
43319585STim.Szeto@Sun.COM 				break;
43329585STim.Szeto@Sun.COM 		}
43339585STim.Szeto@Sun.COM 		goto done;
43349585STim.Szeto@Sun.COM 	}
43359585STim.Szeto@Sun.COM 	/*
43369585STim.Szeto@Sun.COM 	 * Check whether input buffer was large enough
43379585STim.Szeto@Sun.COM 	 */
43389585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_VE) {
43399585STim.Szeto@Sun.COM 		bzero(&stmfIoctl, sizeof (stmfIoctl));
43409585STim.Szeto@Sun.COM 		fVeListSize = stmfIoctl.stmf_obuf_max_nentries *
43419585STim.Szeto@Sun.COM 		    sizeof (stmf_view_op_entry_t);
43429585STim.Szeto@Sun.COM 		free(fVeList);
43439585STim.Szeto@Sun.COM 		fVeList = (stmf_view_op_entry_t *)calloc(1, fVeListSize);
43449585STim.Szeto@Sun.COM 		if (fVeList == NULL) {
43459585STim.Szeto@Sun.COM 			return (STMF_ERROR_NOMEM);
43469585STim.Szeto@Sun.COM 		}
43479585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf_size = fVeListSize;
43489585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fVeList;
43499585STim.Szeto@Sun.COM 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
43509585STim.Szeto@Sun.COM 		if (ioctlRet != 0) {
43519585STim.Szeto@Sun.COM 			switch (errno) {
43529585STim.Szeto@Sun.COM 				case EBUSY:
43539585STim.Szeto@Sun.COM 					ret = STMF_ERROR_BUSY;
43549585STim.Szeto@Sun.COM 					break;
43559585STim.Szeto@Sun.COM 				case EPERM:
43569585STim.Szeto@Sun.COM 				case EACCES:
43579585STim.Szeto@Sun.COM 					ret = STMF_ERROR_PERM;
43589585STim.Szeto@Sun.COM 					break;
43599585STim.Szeto@Sun.COM 				default:
43609585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
43619585STim.Szeto@Sun.COM 					    "stmfGetLogicalUnitList:"
43629585STim.Szeto@Sun.COM 					    "ioctl errno(%d)", errno);
43639585STim.Szeto@Sun.COM 					ret = STMF_STATUS_ERROR;
43649585STim.Szeto@Sun.COM 					break;
43659585STim.Szeto@Sun.COM 			}
43669585STim.Szeto@Sun.COM 			goto done;
43679585STim.Szeto@Sun.COM 		}
43689585STim.Szeto@Sun.COM 	}
43699585STim.Szeto@Sun.COM 
43709585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
43719585STim.Szeto@Sun.COM 		goto done;
43729585STim.Szeto@Sun.COM 	}
43739585STim.Szeto@Sun.COM 
43749585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_nentries == 0) {
43759585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOT_FOUND;
43769585STim.Szeto@Sun.COM 		goto done;
43779585STim.Szeto@Sun.COM 	}
43789585STim.Szeto@Sun.COM 
43799585STim.Szeto@Sun.COM 	listCnt = stmfIoctl.stmf_obuf_nentries;
43809585STim.Szeto@Sun.COM 
43819585STim.Szeto@Sun.COM 	/*
43829585STim.Szeto@Sun.COM 	 * allocate caller's buffer with the final size
43839585STim.Szeto@Sun.COM 	 */
43849585STim.Szeto@Sun.COM 	*viewEntryList = (stmfViewEntryList *)calloc(1,
43859585STim.Szeto@Sun.COM 	    sizeof (stmfViewEntryList) + listCnt * sizeof (stmfViewEntry));
43869585STim.Szeto@Sun.COM 	if (*viewEntryList == NULL) {
43879585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
43889585STim.Szeto@Sun.COM 		goto done;
43899585STim.Szeto@Sun.COM 	}
43909585STim.Szeto@Sun.COM 
43919585STim.Szeto@Sun.COM 	(*viewEntryList)->cnt = listCnt;
43929585STim.Szeto@Sun.COM 
43939585STim.Szeto@Sun.COM 	/* copy to caller's buffer */
43949585STim.Szeto@Sun.COM 	for (i = 0; i < listCnt; i++) {
43959585STim.Szeto@Sun.COM 		(*viewEntryList)->ve[i].veIndexValid = B_TRUE;
43969585STim.Szeto@Sun.COM 		(*viewEntryList)->ve[i].veIndex = fVeList[i].ve_ndx;
43979585STim.Szeto@Sun.COM 		if (fVeList[i].ve_all_hosts == 1) {
43989585STim.Szeto@Sun.COM 			(*viewEntryList)->ve[i].allHosts = B_TRUE;
43999585STim.Szeto@Sun.COM 		} else {
44009585STim.Szeto@Sun.COM 			bcopy(fVeList[i].ve_host_group.name,
44019585STim.Szeto@Sun.COM 			    (*viewEntryList)->ve[i].hostGroup,
44029585STim.Szeto@Sun.COM 			    fVeList[i].ve_host_group.name_size);
44039585STim.Szeto@Sun.COM 		}
44049585STim.Szeto@Sun.COM 		if (fVeList[i].ve_all_targets == 1) {
44059585STim.Szeto@Sun.COM 			(*viewEntryList)->ve[i].allTargets = B_TRUE;
44069585STim.Szeto@Sun.COM 		} else {
44079585STim.Szeto@Sun.COM 			bcopy(fVeList[i].ve_target_group.name,
44089585STim.Szeto@Sun.COM 			    (*viewEntryList)->ve[i].targetGroup,
44099585STim.Szeto@Sun.COM 			    fVeList[i].ve_target_group.name_size);
44109585STim.Szeto@Sun.COM 		}
44119585STim.Szeto@Sun.COM 		bcopy(fVeList[i].ve_lu_nbr, (*viewEntryList)->ve[i].luNbr,
44129585STim.Szeto@Sun.COM 		    sizeof ((*viewEntryList)->ve[i].luNbr));
44139585STim.Szeto@Sun.COM 		(*viewEntryList)->ve[i].luNbrValid = B_TRUE;
44149585STim.Szeto@Sun.COM 	}
44159585STim.Szeto@Sun.COM 
44169585STim.Szeto@Sun.COM 	/*
44179585STim.Szeto@Sun.COM 	 * sort the list. This gives a consistent view across gets
44189585STim.Szeto@Sun.COM 	 */
44199585STim.Szeto@Sun.COM 	qsort((void *)&((*viewEntryList)->ve[0]), (*viewEntryList)->cnt,
44209585STim.Szeto@Sun.COM 	    sizeof (stmfViewEntry), viewEntryCompare);
44219585STim.Szeto@Sun.COM 
44229585STim.Szeto@Sun.COM done:
44239585STim.Szeto@Sun.COM 	(void) close(fd);
44249585STim.Szeto@Sun.COM 	/*
44259585STim.Szeto@Sun.COM 	 * free internal buffers
44269585STim.Szeto@Sun.COM 	 */
44279585STim.Szeto@Sun.COM 	free(fVeList);
44287836SJohn.Forte@Sun.COM 	return (ret);
44297836SJohn.Forte@Sun.COM }
44307836SJohn.Forte@Sun.COM 
44319585STim.Szeto@Sun.COM 
44327836SJohn.Forte@Sun.COM /*
44337836SJohn.Forte@Sun.COM  * loadHostGroups
44347836SJohn.Forte@Sun.COM  *
44357836SJohn.Forte@Sun.COM  * Purpose - issues the ioctl to load the host groups into stmf
44367836SJohn.Forte@Sun.COM  *
44377836SJohn.Forte@Sun.COM  * fd - file descriptor for the control node of stmf.
44387836SJohn.Forte@Sun.COM  * groupList - populated host group list
44397836SJohn.Forte@Sun.COM  */
44407836SJohn.Forte@Sun.COM static int
44417836SJohn.Forte@Sun.COM loadHostGroups(int fd, stmfGroupList *groupList)
44427836SJohn.Forte@Sun.COM {
44437836SJohn.Forte@Sun.COM 	int i, j;
44447836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
44457836SJohn.Forte@Sun.COM 	stmfGroupProperties *groupProps = NULL;
44467836SJohn.Forte@Sun.COM 
44477836SJohn.Forte@Sun.COM 	for (i = 0; i < groupList->cnt; i++) {
44487836SJohn.Forte@Sun.COM 		if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_HOST_GROUP,
44497836SJohn.Forte@Sun.COM 		    &(groupList->name[i]))) != STMF_STATUS_SUCCESS) {
44507836SJohn.Forte@Sun.COM 			goto out;
44517836SJohn.Forte@Sun.COM 		}
44529585STim.Szeto@Sun.COM 		ret = iLoadGroupMembersFromPs(&(groupList->name[i]),
44539585STim.Szeto@Sun.COM 		    &groupProps, HOST_GROUP);
44547836SJohn.Forte@Sun.COM 		for (j = 0; j < groupProps->cnt; j++) {
44557836SJohn.Forte@Sun.COM 			if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_HG_ENTRY,
44567836SJohn.Forte@Sun.COM 			    &(groupList->name[i]), &(groupProps->name[j])))
44577836SJohn.Forte@Sun.COM 			    != STMF_STATUS_SUCCESS) {
44587836SJohn.Forte@Sun.COM 				goto out;
44597836SJohn.Forte@Sun.COM 			}
44607836SJohn.Forte@Sun.COM 		}
44617836SJohn.Forte@Sun.COM 	}
44627836SJohn.Forte@Sun.COM 
44637836SJohn.Forte@Sun.COM 
44647836SJohn.Forte@Sun.COM out:
44657836SJohn.Forte@Sun.COM 	stmfFreeMemory(groupProps);
44667836SJohn.Forte@Sun.COM 	return (ret);
44677836SJohn.Forte@Sun.COM }
44687836SJohn.Forte@Sun.COM 
44697836SJohn.Forte@Sun.COM /*
44707836SJohn.Forte@Sun.COM  * loadTargetGroups
44717836SJohn.Forte@Sun.COM  *
44727836SJohn.Forte@Sun.COM  * Purpose - issues the ioctl to load the target groups into stmf
44737836SJohn.Forte@Sun.COM  *
44747836SJohn.Forte@Sun.COM  * fd - file descriptor for the control node of stmf.
44757836SJohn.Forte@Sun.COM  * groupList - populated target group list.
44767836SJohn.Forte@Sun.COM  */
44777836SJohn.Forte@Sun.COM static int
44787836SJohn.Forte@Sun.COM loadTargetGroups(int fd, stmfGroupList *groupList)
44797836SJohn.Forte@Sun.COM {
44807836SJohn.Forte@Sun.COM 	int i, j;
44817836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
44827836SJohn.Forte@Sun.COM 	stmfGroupProperties *groupProps = NULL;
44837836SJohn.Forte@Sun.COM 
44847836SJohn.Forte@Sun.COM 	for (i = 0; i < groupList->cnt; i++) {
44857836SJohn.Forte@Sun.COM 		if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_TARGET_GROUP,
44867836SJohn.Forte@Sun.COM 		    &(groupList->name[i]))) != STMF_STATUS_SUCCESS) {
44877836SJohn.Forte@Sun.COM 			goto out;
44887836SJohn.Forte@Sun.COM 		}
44899585STim.Szeto@Sun.COM 		ret = iLoadGroupMembersFromPs(&(groupList->name[i]),
44909585STim.Szeto@Sun.COM 		    &groupProps, TARGET_GROUP);
44917836SJohn.Forte@Sun.COM 		for (j = 0; j < groupProps->cnt; j++) {
44927836SJohn.Forte@Sun.COM 			if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_TG_ENTRY,
44937836SJohn.Forte@Sun.COM 			    &(groupList->name[i]), &(groupProps->name[j])))
44947836SJohn.Forte@Sun.COM 			    != STMF_STATUS_SUCCESS) {
44957836SJohn.Forte@Sun.COM 				goto out;
44967836SJohn.Forte@Sun.COM 			}
44977836SJohn.Forte@Sun.COM 		}
44987836SJohn.Forte@Sun.COM 	}
44997836SJohn.Forte@Sun.COM 
45007836SJohn.Forte@Sun.COM 
45017836SJohn.Forte@Sun.COM out:
45027836SJohn.Forte@Sun.COM 	stmfFreeMemory(groupProps);
45037836SJohn.Forte@Sun.COM 	return (ret);
45047836SJohn.Forte@Sun.COM }
45057836SJohn.Forte@Sun.COM 
45067836SJohn.Forte@Sun.COM 
45077836SJohn.Forte@Sun.COM /*
45087836SJohn.Forte@Sun.COM  * loadStore
45097836SJohn.Forte@Sun.COM  *
45107836SJohn.Forte@Sun.COM  * Purpose: Load the configuration data from the store
45117836SJohn.Forte@Sun.COM  *
45127836SJohn.Forte@Sun.COM  * First load the host groups and target groups, then the view entries
45137836SJohn.Forte@Sun.COM  * and finally the provider data
45147836SJohn.Forte@Sun.COM  *
45157836SJohn.Forte@Sun.COM  * fd - file descriptor of control node for stmf.
45167836SJohn.Forte@Sun.COM  */
45177836SJohn.Forte@Sun.COM static int
45187836SJohn.Forte@Sun.COM loadStore(int fd)
45197836SJohn.Forte@Sun.COM {
45207836SJohn.Forte@Sun.COM 	int ret;
45217836SJohn.Forte@Sun.COM 	int i, j;
45227836SJohn.Forte@Sun.COM 	stmfGroupList *groupList = NULL;
45237836SJohn.Forte@Sun.COM 	stmfGuidList *guidList = NULL;
45247836SJohn.Forte@Sun.COM 	stmfViewEntryList *viewEntryList = NULL;
45257836SJohn.Forte@Sun.COM 	stmfProviderList *providerList = NULL;
45267836SJohn.Forte@Sun.COM 	int providerType;
45277836SJohn.Forte@Sun.COM 	nvlist_t *nvl = NULL;
45287836SJohn.Forte@Sun.COM 
45297836SJohn.Forte@Sun.COM 
45307836SJohn.Forte@Sun.COM 
45317836SJohn.Forte@Sun.COM 	/* load host groups */
45329585STim.Szeto@Sun.COM 	ret = iLoadGroupFromPs(&groupList, HOST_GROUP);
45337836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
45347836SJohn.Forte@Sun.COM 		return (ret);
45357836SJohn.Forte@Sun.COM 	}
45367836SJohn.Forte@Sun.COM 	ret = loadHostGroups(fd, groupList);
45377836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
45387836SJohn.Forte@Sun.COM 		goto out;
45397836SJohn.Forte@Sun.COM 	}
45407836SJohn.Forte@Sun.COM 
45417836SJohn.Forte@Sun.COM 	stmfFreeMemory(groupList);
45427836SJohn.Forte@Sun.COM 	groupList = NULL;
45437836SJohn.Forte@Sun.COM 
45447836SJohn.Forte@Sun.COM 	/* load target groups */
45459585STim.Szeto@Sun.COM 	ret = iLoadGroupFromPs(&groupList, TARGET_GROUP);
45467836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
45477836SJohn.Forte@Sun.COM 		goto out;
45487836SJohn.Forte@Sun.COM 	}
45497836SJohn.Forte@Sun.COM 	ret = loadTargetGroups(fd, groupList);
45507836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
45517836SJohn.Forte@Sun.COM 		goto out;
45527836SJohn.Forte@Sun.COM 	}
45537836SJohn.Forte@Sun.COM 
45547836SJohn.Forte@Sun.COM 	stmfFreeMemory(groupList);
45557836SJohn.Forte@Sun.COM 	groupList = NULL;
45567836SJohn.Forte@Sun.COM 
45577836SJohn.Forte@Sun.COM 	/* Get the guid list */
45587836SJohn.Forte@Sun.COM 	ret = psGetLogicalUnitList(&guidList);
45597836SJohn.Forte@Sun.COM 	switch (ret) {
45607836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
45617836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
45627836SJohn.Forte@Sun.COM 			break;
45637836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
45647836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
45657836SJohn.Forte@Sun.COM 			break;
45667836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
45677836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
45687836SJohn.Forte@Sun.COM 			break;
45697836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
45707836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
45717836SJohn.Forte@Sun.COM 			break;
45727836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
45737836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
45747836SJohn.Forte@Sun.COM 			break;
45757836SJohn.Forte@Sun.COM 		default:
45767836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
45777836SJohn.Forte@Sun.COM 			break;
45787836SJohn.Forte@Sun.COM 	}
45797836SJohn.Forte@Sun.COM 
45807836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
45817836SJohn.Forte@Sun.COM 		goto out;
45827836SJohn.Forte@Sun.COM 	}
45837836SJohn.Forte@Sun.COM 
45847836SJohn.Forte@Sun.COM 	/*
45857836SJohn.Forte@Sun.COM 	 * We have the guid list, now get the corresponding
45867836SJohn.Forte@Sun.COM 	 * view entries for each guid
45877836SJohn.Forte@Sun.COM 	 */
45887836SJohn.Forte@Sun.COM 	for (i = 0; i < guidList->cnt; i++) {
45897836SJohn.Forte@Sun.COM 		ret = psGetViewEntryList(&guidList->guid[i], &viewEntryList);
45907836SJohn.Forte@Sun.COM 		switch (ret) {
45917836SJohn.Forte@Sun.COM 			case STMF_PS_SUCCESS:
45927836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_SUCCESS;
45937836SJohn.Forte@Sun.COM 				break;
45947836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_NOT_FOUND:
45957836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
45967836SJohn.Forte@Sun.COM 				break;
45977836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_BUSY:
45987836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
45997836SJohn.Forte@Sun.COM 				break;
46007836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_SERVICE_NOT_FOUND:
46017836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_SERVICE_NOT_FOUND;
46027836SJohn.Forte@Sun.COM 				break;
46037836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_VERSION_MISMATCH:
46047836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_SERVICE_DATA_VERSION;
46057836SJohn.Forte@Sun.COM 				break;
46067836SJohn.Forte@Sun.COM 			default:
46077836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
46087836SJohn.Forte@Sun.COM 				break;
46097836SJohn.Forte@Sun.COM 		}
46107836SJohn.Forte@Sun.COM 		if (ret != STMF_STATUS_SUCCESS) {
46117836SJohn.Forte@Sun.COM 			goto out;
46127836SJohn.Forte@Sun.COM 		}
46137836SJohn.Forte@Sun.COM 		for (j = 0; j < viewEntryList->cnt; j++) {
46147836SJohn.Forte@Sun.COM 			ret = addViewEntryIoctl(fd, &guidList->guid[i],
46157836SJohn.Forte@Sun.COM 			    &viewEntryList->ve[j]);
46167836SJohn.Forte@Sun.COM 			if (ret != STMF_STATUS_SUCCESS) {
46177836SJohn.Forte@Sun.COM 				goto out;
46187836SJohn.Forte@Sun.COM 			}
46197836SJohn.Forte@Sun.COM 		}
46207836SJohn.Forte@Sun.COM 	}
46217836SJohn.Forte@Sun.COM 
46227836SJohn.Forte@Sun.COM 	/* get the list of providers that have data */
46237836SJohn.Forte@Sun.COM 	ret = psGetProviderDataList(&providerList);
46247836SJohn.Forte@Sun.COM 	switch (ret) {
46257836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
46267836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
46277836SJohn.Forte@Sun.COM 			break;
46287836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
46297836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
46307836SJohn.Forte@Sun.COM 			break;
46317836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
46327836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
46337836SJohn.Forte@Sun.COM 			break;
46347836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
46357836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
46367836SJohn.Forte@Sun.COM 			break;
46377836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
46387836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
46397836SJohn.Forte@Sun.COM 			break;
46407836SJohn.Forte@Sun.COM 		default:
46417836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
46427836SJohn.Forte@Sun.COM 			break;
46437836SJohn.Forte@Sun.COM 	}
46447836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
46457836SJohn.Forte@Sun.COM 		goto out;
46467836SJohn.Forte@Sun.COM 	}
46477836SJohn.Forte@Sun.COM 
46487836SJohn.Forte@Sun.COM 	for (i = 0; i < providerList->cnt; i++) {
46497836SJohn.Forte@Sun.COM 		providerType = providerList->provider[i].providerType;
46507836SJohn.Forte@Sun.COM 		ret = psGetProviderData(providerList->provider[i].name,
46517836SJohn.Forte@Sun.COM 		    &nvl, providerType, NULL);
46527836SJohn.Forte@Sun.COM 		switch (ret) {
46537836SJohn.Forte@Sun.COM 			case STMF_PS_SUCCESS:
46547836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_SUCCESS;
46557836SJohn.Forte@Sun.COM 				break;
46567836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_NOT_FOUND:
46577836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
46587836SJohn.Forte@Sun.COM 				break;
46597836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_BUSY:
46607836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
46617836SJohn.Forte@Sun.COM 				break;
46627836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_SERVICE_NOT_FOUND:
46637836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_SERVICE_NOT_FOUND;
46647836SJohn.Forte@Sun.COM 				break;
46657836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_VERSION_MISMATCH:
46667836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_SERVICE_DATA_VERSION;
46677836SJohn.Forte@Sun.COM 				break;
46687836SJohn.Forte@Sun.COM 			default:
46697836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
46707836SJohn.Forte@Sun.COM 				break;
46717836SJohn.Forte@Sun.COM 		}
46727836SJohn.Forte@Sun.COM 		if (ret != STMF_STATUS_SUCCESS) {
46737836SJohn.Forte@Sun.COM 			goto out;
46747836SJohn.Forte@Sun.COM 		}
46757836SJohn.Forte@Sun.COM 
46767836SJohn.Forte@Sun.COM 		/* call setProviderData */
46777836SJohn.Forte@Sun.COM 		ret = setProviderData(fd, providerList->provider[i].name, nvl,
46789585STim.Szeto@Sun.COM 		    providerType, NULL);
46797836SJohn.Forte@Sun.COM 		switch (ret) {
46807836SJohn.Forte@Sun.COM 			case STMF_PS_SUCCESS:
46817836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_SUCCESS;
46827836SJohn.Forte@Sun.COM 				break;
46837836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_NOT_FOUND:
46847836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
46857836SJohn.Forte@Sun.COM 				break;
46867836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_BUSY:
46877836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
46887836SJohn.Forte@Sun.COM 				break;
46897836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_SERVICE_NOT_FOUND:
46907836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_SERVICE_NOT_FOUND;
46917836SJohn.Forte@Sun.COM 				break;
46927836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_VERSION_MISMATCH:
46937836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_SERVICE_DATA_VERSION;
46947836SJohn.Forte@Sun.COM 				break;
46957836SJohn.Forte@Sun.COM 			default:
46967836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
46977836SJohn.Forte@Sun.COM 				break;
46987836SJohn.Forte@Sun.COM 		}
46997836SJohn.Forte@Sun.COM 		if (ret != STMF_STATUS_SUCCESS) {
47007836SJohn.Forte@Sun.COM 			goto out;
47017836SJohn.Forte@Sun.COM 		}
47027836SJohn.Forte@Sun.COM 
47037836SJohn.Forte@Sun.COM 		nvlist_free(nvl);
47047836SJohn.Forte@Sun.COM 		nvl = NULL;
47057836SJohn.Forte@Sun.COM 	}
47067836SJohn.Forte@Sun.COM out:
47077836SJohn.Forte@Sun.COM 	if (groupList != NULL) {
47087836SJohn.Forte@Sun.COM 		free(groupList);
47097836SJohn.Forte@Sun.COM 	}
47107836SJohn.Forte@Sun.COM 	if (guidList != NULL) {
47117836SJohn.Forte@Sun.COM 		free(guidList);
47127836SJohn.Forte@Sun.COM 	}
47137836SJohn.Forte@Sun.COM 	if (viewEntryList != NULL) {
47147836SJohn.Forte@Sun.COM 		free(viewEntryList);
47157836SJohn.Forte@Sun.COM 	}
47167836SJohn.Forte@Sun.COM 	if (nvl != NULL) {
47177836SJohn.Forte@Sun.COM 		nvlist_free(nvl);
47187836SJohn.Forte@Sun.COM 	}
47197836SJohn.Forte@Sun.COM 	return (ret);
47207836SJohn.Forte@Sun.COM }
47217836SJohn.Forte@Sun.COM 
47227836SJohn.Forte@Sun.COM /*
47237836SJohn.Forte@Sun.COM  * stmfLoadConfig
47247836SJohn.Forte@Sun.COM  *
47257836SJohn.Forte@Sun.COM  * Purpose - load the configuration data from smf into stmf
47267836SJohn.Forte@Sun.COM  *
47277836SJohn.Forte@Sun.COM  */
47287836SJohn.Forte@Sun.COM int
47297836SJohn.Forte@Sun.COM stmfLoadConfig(void)
47307836SJohn.Forte@Sun.COM {
47319585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
47327836SJohn.Forte@Sun.COM 	int fd;
47337836SJohn.Forte@Sun.COM 	stmf_state_desc_t stmfStateSet;
47347836SJohn.Forte@Sun.COM 	stmfState state;
47357836SJohn.Forte@Sun.COM 
47369585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
47379585STim.Szeto@Sun.COM 		stmfStateSet.state = STMF_STATE_OFFLINE;
473810560SSusan.Gleeson@Sun.COM 
47399585STim.Szeto@Sun.COM 		if ((ret = openStmf(OPEN_EXCL_STMF, &fd))
47409585STim.Szeto@Sun.COM 		    != STMF_STATUS_SUCCESS) {
47419585STim.Szeto@Sun.COM 			return (ret);
47429585STim.Szeto@Sun.COM 		}
474310560SSusan.Gleeson@Sun.COM 		/*
474410560SSusan.Gleeson@Sun.COM 		 * Configuration not stored persistently; nothing to
474510560SSusan.Gleeson@Sun.COM 		 * initialize so do not set to STMF_CONFIG_INIT.
474610560SSusan.Gleeson@Sun.COM 		 */
47479585STim.Szeto@Sun.COM 		stmfStateSet.config_state = STMF_CONFIG_INIT_DONE;
47489585STim.Szeto@Sun.COM 		goto done;
47499585STim.Szeto@Sun.COM 	}
47507836SJohn.Forte@Sun.COM 
47517836SJohn.Forte@Sun.COM 	/* Check to ensure service exists */
47527836SJohn.Forte@Sun.COM 	if (psCheckService() != STMF_STATUS_SUCCESS) {
47537836SJohn.Forte@Sun.COM 		return (STMF_ERROR_SERVICE_NOT_FOUND);
47547836SJohn.Forte@Sun.COM 	}
47557836SJohn.Forte@Sun.COM 
47567836SJohn.Forte@Sun.COM 	ret = stmfGetState(&state);
47577836SJohn.Forte@Sun.COM 	if (ret == STMF_STATUS_SUCCESS) {
47587836SJohn.Forte@Sun.COM 		if (state.operationalState != STMF_SERVICE_STATE_OFFLINE) {
47597836SJohn.Forte@Sun.COM 			return (STMF_ERROR_SERVICE_ONLINE);
47607836SJohn.Forte@Sun.COM 		}
47617836SJohn.Forte@Sun.COM 	} else {
47627836SJohn.Forte@Sun.COM 		return (STMF_STATUS_ERROR);
47637836SJohn.Forte@Sun.COM 	}
47647836SJohn.Forte@Sun.COM 
47657836SJohn.Forte@Sun.COM 
47667836SJohn.Forte@Sun.COM 	stmfStateSet.state = STMF_STATE_OFFLINE;
47677836SJohn.Forte@Sun.COM 	stmfStateSet.config_state = STMF_CONFIG_INIT;
47687836SJohn.Forte@Sun.COM 
47697836SJohn.Forte@Sun.COM 	/*
47707836SJohn.Forte@Sun.COM 	 * Open control node for stmf
47717836SJohn.Forte@Sun.COM 	 */
47727836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
47737836SJohn.Forte@Sun.COM 		return (ret);
47747836SJohn.Forte@Sun.COM 
47757836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE);
47767836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
47777836SJohn.Forte@Sun.COM 		goto done;
47787836SJohn.Forte@Sun.COM 	}
47797836SJohn.Forte@Sun.COM 
47807836SJohn.Forte@Sun.COM 	/* Load the persistent configuration data */
47817836SJohn.Forte@Sun.COM 	ret = loadStore(fd);
47827836SJohn.Forte@Sun.COM 	if (ret != 0) {
47837836SJohn.Forte@Sun.COM 		goto done;
47847836SJohn.Forte@Sun.COM 	}
47857836SJohn.Forte@Sun.COM 
47867836SJohn.Forte@Sun.COM 	stmfStateSet.state = STMF_STATE_OFFLINE;
47877836SJohn.Forte@Sun.COM 	stmfStateSet.config_state = STMF_CONFIG_INIT_DONE;
47887836SJohn.Forte@Sun.COM 
47897836SJohn.Forte@Sun.COM done:
47907836SJohn.Forte@Sun.COM 	if (ret == STMF_STATUS_SUCCESS) {
47917836SJohn.Forte@Sun.COM 		ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE);
47927836SJohn.Forte@Sun.COM 	}
47937836SJohn.Forte@Sun.COM 	(void) close(fd);
47947836SJohn.Forte@Sun.COM 	return (ret);
47957836SJohn.Forte@Sun.COM }
47967836SJohn.Forte@Sun.COM 
47979585STim.Szeto@Sun.COM 
47987836SJohn.Forte@Sun.COM /*
47997836SJohn.Forte@Sun.COM  * getStmfState
48007836SJohn.Forte@Sun.COM  *
48017836SJohn.Forte@Sun.COM  * stmfState - pointer to stmf_state_desc_t structure. Will contain the state
48027836SJohn.Forte@Sun.COM  *             information of the stmf service on success.
48037836SJohn.Forte@Sun.COM  */
48047836SJohn.Forte@Sun.COM static int
48057836SJohn.Forte@Sun.COM getStmfState(stmf_state_desc_t *stmfState)
48067836SJohn.Forte@Sun.COM {
48077836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
48087836SJohn.Forte@Sun.COM 	int fd;
48097836SJohn.Forte@Sun.COM 	int ioctlRet;
48107836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
48117836SJohn.Forte@Sun.COM 
48127836SJohn.Forte@Sun.COM 	/*
48137836SJohn.Forte@Sun.COM 	 * Open control node for stmf
48147836SJohn.Forte@Sun.COM 	 */
48157836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
48167836SJohn.Forte@Sun.COM 		return (ret);
48177836SJohn.Forte@Sun.COM 
48187836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
48197836SJohn.Forte@Sun.COM 	/*
48207836SJohn.Forte@Sun.COM 	 * Issue ioctl to get the stmf state
48217836SJohn.Forte@Sun.COM 	 */
48227836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
48237836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (stmf_state_desc_t);
48247836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)stmfState;
48257836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = sizeof (stmf_state_desc_t);
48267836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)stmfState;
48277836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_GET_STMF_STATE, &stmfIoctl);
48287836SJohn.Forte@Sun.COM 
48297836SJohn.Forte@Sun.COM 	(void) close(fd);
48307836SJohn.Forte@Sun.COM 
48317836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
48327836SJohn.Forte@Sun.COM 		switch (errno) {
48337836SJohn.Forte@Sun.COM 			case EBUSY:
48347836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
48357836SJohn.Forte@Sun.COM 				break;
48367836SJohn.Forte@Sun.COM 			case EPERM:
48377836SJohn.Forte@Sun.COM 			case EACCES:
48387836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
48397836SJohn.Forte@Sun.COM 				break;
48407836SJohn.Forte@Sun.COM 			default:
48417836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
48427836SJohn.Forte@Sun.COM 				    "getStmfState:ioctl errno(%d)", errno);
48437836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
48447836SJohn.Forte@Sun.COM 				break;
48457836SJohn.Forte@Sun.COM 		}
48467836SJohn.Forte@Sun.COM 	}
48477836SJohn.Forte@Sun.COM 	return (ret);
48487836SJohn.Forte@Sun.COM }
48497836SJohn.Forte@Sun.COM 
48507836SJohn.Forte@Sun.COM 
48517836SJohn.Forte@Sun.COM /*
48527836SJohn.Forte@Sun.COM  * setStmfState
48537836SJohn.Forte@Sun.COM  *
48547836SJohn.Forte@Sun.COM  * stmfState - pointer to caller set state structure
48557836SJohn.Forte@Sun.COM  * objectType - one of:
48567836SJohn.Forte@Sun.COM  *		LOGICAL_UNIT_TYPE
48577836SJohn.Forte@Sun.COM  *		TARGET_TYPE
48587836SJohn.Forte@Sun.COM  *		STMF_SERVICE_TYPE
48597836SJohn.Forte@Sun.COM  */
48607836SJohn.Forte@Sun.COM static int
48617836SJohn.Forte@Sun.COM setStmfState(int fd, stmf_state_desc_t *stmfState, int objectType)
48627836SJohn.Forte@Sun.COM {
48637836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
48647836SJohn.Forte@Sun.COM 	int ioctlRet;
48657836SJohn.Forte@Sun.COM 	int cmd;
48667836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
48677836SJohn.Forte@Sun.COM 
48687836SJohn.Forte@Sun.COM 	switch (objectType) {
48697836SJohn.Forte@Sun.COM 		case LOGICAL_UNIT_TYPE:
48707836SJohn.Forte@Sun.COM 			cmd = STMF_IOCTL_SET_LU_STATE;
48717836SJohn.Forte@Sun.COM 			break;
48727836SJohn.Forte@Sun.COM 		case TARGET_TYPE:
48737836SJohn.Forte@Sun.COM 			cmd = STMF_IOCTL_SET_TARGET_PORT_STATE;
48747836SJohn.Forte@Sun.COM 			break;
48757836SJohn.Forte@Sun.COM 		case STMF_SERVICE_TYPE:
48767836SJohn.Forte@Sun.COM 			cmd = STMF_IOCTL_SET_STMF_STATE;
48777836SJohn.Forte@Sun.COM 			break;
48787836SJohn.Forte@Sun.COM 		default:
48797836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
48807836SJohn.Forte@Sun.COM 			goto done;
48817836SJohn.Forte@Sun.COM 	}
48827836SJohn.Forte@Sun.COM 
48837836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
48847836SJohn.Forte@Sun.COM 	/*
48857836SJohn.Forte@Sun.COM 	 * Issue ioctl to set the stmf state
48867836SJohn.Forte@Sun.COM 	 */
48877836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
48887836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (stmf_state_desc_t);
48897836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)stmfState;
48907836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
48917836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
48927836SJohn.Forte@Sun.COM 		switch (errno) {
48937836SJohn.Forte@Sun.COM 			case EBUSY:
48947836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
48957836SJohn.Forte@Sun.COM 				break;
48969585STim.Szeto@Sun.COM 			case EPERM:
48977836SJohn.Forte@Sun.COM 			case EACCES:
48987836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
48997836SJohn.Forte@Sun.COM 				break;
49007836SJohn.Forte@Sun.COM 			case ENOENT:
49017836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
49027836SJohn.Forte@Sun.COM 				break;
49037836SJohn.Forte@Sun.COM 			default:
49047836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
49057836SJohn.Forte@Sun.COM 				    "setStmfState:ioctl errno(%d)", errno);
49067836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
49077836SJohn.Forte@Sun.COM 				break;
49087836SJohn.Forte@Sun.COM 		}
49097836SJohn.Forte@Sun.COM 	}
49107836SJohn.Forte@Sun.COM done:
49117836SJohn.Forte@Sun.COM 	return (ret);
49127836SJohn.Forte@Sun.COM }
49137836SJohn.Forte@Sun.COM 
49147836SJohn.Forte@Sun.COM /*
49157836SJohn.Forte@Sun.COM  * stmfOnline
49167836SJohn.Forte@Sun.COM  *
49177836SJohn.Forte@Sun.COM  * Purpose: Online stmf service
49187836SJohn.Forte@Sun.COM  *
49197836SJohn.Forte@Sun.COM  */
49207836SJohn.Forte@Sun.COM int
49217836SJohn.Forte@Sun.COM stmfOnline(void)
49227836SJohn.Forte@Sun.COM {
49237836SJohn.Forte@Sun.COM 	int ret;
49247836SJohn.Forte@Sun.COM 	int fd;
49257836SJohn.Forte@Sun.COM 	stmfState state;
49267836SJohn.Forte@Sun.COM 	stmf_state_desc_t iState;
49277836SJohn.Forte@Sun.COM 
49287836SJohn.Forte@Sun.COM 	ret = stmfGetState(&state);
49297836SJohn.Forte@Sun.COM 	if (ret == STMF_STATUS_SUCCESS) {
49307836SJohn.Forte@Sun.COM 		if (state.operationalState == STMF_SERVICE_STATE_ONLINE) {
49317836SJohn.Forte@Sun.COM 			return (STMF_ERROR_SERVICE_ONLINE);
49327836SJohn.Forte@Sun.COM 		}
49337836SJohn.Forte@Sun.COM 	} else {
49347836SJohn.Forte@Sun.COM 		return (STMF_STATUS_ERROR);
49357836SJohn.Forte@Sun.COM 	}
49367836SJohn.Forte@Sun.COM 	iState.state = STMF_STATE_ONLINE;
49377836SJohn.Forte@Sun.COM 	iState.config_state = STMF_CONFIG_NONE;
49387836SJohn.Forte@Sun.COM 	/*
49397836SJohn.Forte@Sun.COM 	 * Open control node for stmf
49407836SJohn.Forte@Sun.COM 	 * to make call to setStmfState()
49417836SJohn.Forte@Sun.COM 	 */
49427836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
49437836SJohn.Forte@Sun.COM 		return (ret);
49447836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &iState, STMF_SERVICE_TYPE);
49457836SJohn.Forte@Sun.COM 	(void) close(fd);
49467836SJohn.Forte@Sun.COM 	return (ret);
49477836SJohn.Forte@Sun.COM }
49487836SJohn.Forte@Sun.COM 
49497836SJohn.Forte@Sun.COM /*
49507836SJohn.Forte@Sun.COM  * stmfOffline
49517836SJohn.Forte@Sun.COM  *
49527836SJohn.Forte@Sun.COM  * Purpose: Offline stmf service
49537836SJohn.Forte@Sun.COM  *
49547836SJohn.Forte@Sun.COM  */
49557836SJohn.Forte@Sun.COM int
49567836SJohn.Forte@Sun.COM stmfOffline(void)
49577836SJohn.Forte@Sun.COM {
49587836SJohn.Forte@Sun.COM 	int ret;
49597836SJohn.Forte@Sun.COM 	int fd;
49607836SJohn.Forte@Sun.COM 	stmfState state;
49617836SJohn.Forte@Sun.COM 	stmf_state_desc_t iState;
49627836SJohn.Forte@Sun.COM 
49637836SJohn.Forte@Sun.COM 	ret = stmfGetState(&state);
49647836SJohn.Forte@Sun.COM 	if (ret == STMF_STATUS_SUCCESS) {
49657836SJohn.Forte@Sun.COM 		if (state.operationalState == STMF_SERVICE_STATE_OFFLINE) {
49667836SJohn.Forte@Sun.COM 			return (STMF_ERROR_SERVICE_OFFLINE);
49677836SJohn.Forte@Sun.COM 		}
49687836SJohn.Forte@Sun.COM 	} else {
49697836SJohn.Forte@Sun.COM 		return (STMF_STATUS_ERROR);
49707836SJohn.Forte@Sun.COM 	}
49717836SJohn.Forte@Sun.COM 	iState.state = STMF_STATE_OFFLINE;
49727836SJohn.Forte@Sun.COM 	iState.config_state = STMF_CONFIG_NONE;
49737836SJohn.Forte@Sun.COM 
49747836SJohn.Forte@Sun.COM 	/*
49757836SJohn.Forte@Sun.COM 	 * Open control node for stmf
49767836SJohn.Forte@Sun.COM 	 * to make call to setStmfState()
49777836SJohn.Forte@Sun.COM 	 */
49787836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
49797836SJohn.Forte@Sun.COM 		return (ret);
49807836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &iState, STMF_SERVICE_TYPE);
49817836SJohn.Forte@Sun.COM 	(void) close(fd);
49827836SJohn.Forte@Sun.COM 	return (ret);
49837836SJohn.Forte@Sun.COM }
49847836SJohn.Forte@Sun.COM 
49857836SJohn.Forte@Sun.COM 
49867836SJohn.Forte@Sun.COM /*
49877836SJohn.Forte@Sun.COM  * stmfOfflineTarget
49887836SJohn.Forte@Sun.COM  *
49897836SJohn.Forte@Sun.COM  * Purpose: Change state of target to offline
49907836SJohn.Forte@Sun.COM  *
49917836SJohn.Forte@Sun.COM  * devid - devid of the target to offline
49927836SJohn.Forte@Sun.COM  */
49937836SJohn.Forte@Sun.COM int
49947836SJohn.Forte@Sun.COM stmfOfflineTarget(stmfDevid *devid)
49957836SJohn.Forte@Sun.COM {
49967836SJohn.Forte@Sun.COM 	stmf_state_desc_t targetState;
49977836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
49987836SJohn.Forte@Sun.COM 	int fd;
49997836SJohn.Forte@Sun.COM 
50007836SJohn.Forte@Sun.COM 	if (devid == NULL) {
50017836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
50027836SJohn.Forte@Sun.COM 	}
50037836SJohn.Forte@Sun.COM 	bzero(&targetState, sizeof (targetState));
50047836SJohn.Forte@Sun.COM 
50057836SJohn.Forte@Sun.COM 	targetState.state = STMF_STATE_OFFLINE;
50067836SJohn.Forte@Sun.COM 	targetState.ident[IDENT_LENGTH_BYTE] = devid->identLength;
50077836SJohn.Forte@Sun.COM 	bcopy(&(devid->ident), &targetState.ident[IDENT_LENGTH_BYTE + 1],
50087836SJohn.Forte@Sun.COM 	    devid->identLength);
50097836SJohn.Forte@Sun.COM 	/*
50107836SJohn.Forte@Sun.COM 	 * Open control node for stmf
50117836SJohn.Forte@Sun.COM 	 * to make call to setStmfState()
50127836SJohn.Forte@Sun.COM 	 */
50137836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
50147836SJohn.Forte@Sun.COM 		return (ret);
50157836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &targetState, TARGET_TYPE);
50167836SJohn.Forte@Sun.COM 	(void) close(fd);
50177836SJohn.Forte@Sun.COM 	return (ret);
50187836SJohn.Forte@Sun.COM }
50197836SJohn.Forte@Sun.COM 
50207836SJohn.Forte@Sun.COM /*
50217836SJohn.Forte@Sun.COM  * stmfOfflineLogicalUnit
50227836SJohn.Forte@Sun.COM  *
50237836SJohn.Forte@Sun.COM  * Purpose: Change state of logical unit to offline
50247836SJohn.Forte@Sun.COM  *
50257836SJohn.Forte@Sun.COM  * lu - guid of the logical unit to offline
50267836SJohn.Forte@Sun.COM  */
50277836SJohn.Forte@Sun.COM int
50287836SJohn.Forte@Sun.COM stmfOfflineLogicalUnit(stmfGuid *lu)
50297836SJohn.Forte@Sun.COM {
50307836SJohn.Forte@Sun.COM 	stmf_state_desc_t luState;
50317836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
50327836SJohn.Forte@Sun.COM 	int fd;
50337836SJohn.Forte@Sun.COM 
50347836SJohn.Forte@Sun.COM 	if (lu == NULL) {
50357836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
50367836SJohn.Forte@Sun.COM 	}
50377836SJohn.Forte@Sun.COM 
50387836SJohn.Forte@Sun.COM 	bzero(&luState, sizeof (luState));
50397836SJohn.Forte@Sun.COM 
50407836SJohn.Forte@Sun.COM 	luState.state = STMF_STATE_OFFLINE;
50417836SJohn.Forte@Sun.COM 	bcopy(lu, &luState.ident, sizeof (stmfGuid));
50427836SJohn.Forte@Sun.COM 	/*
50437836SJohn.Forte@Sun.COM 	 * Open control node for stmf
50447836SJohn.Forte@Sun.COM 	 * to make call to setStmfState()
50457836SJohn.Forte@Sun.COM 	 */
50467836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
50477836SJohn.Forte@Sun.COM 		return (ret);
50487836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &luState, LOGICAL_UNIT_TYPE);
50497836SJohn.Forte@Sun.COM 	(void) close(fd);
50507836SJohn.Forte@Sun.COM 	return (ret);
50517836SJohn.Forte@Sun.COM }
50527836SJohn.Forte@Sun.COM 
50537836SJohn.Forte@Sun.COM /*
50547836SJohn.Forte@Sun.COM  * stmfOnlineTarget
50557836SJohn.Forte@Sun.COM  *
50567836SJohn.Forte@Sun.COM  * Purpose: Change state of target to online
50577836SJohn.Forte@Sun.COM  *
50587836SJohn.Forte@Sun.COM  * devid - devid of the target to online
50597836SJohn.Forte@Sun.COM  */
50607836SJohn.Forte@Sun.COM int
50617836SJohn.Forte@Sun.COM stmfOnlineTarget(stmfDevid *devid)
50627836SJohn.Forte@Sun.COM {
50637836SJohn.Forte@Sun.COM 	stmf_state_desc_t targetState;
50647836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
50657836SJohn.Forte@Sun.COM 	int fd;
50667836SJohn.Forte@Sun.COM 
50677836SJohn.Forte@Sun.COM 	if (devid == NULL) {
50687836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
50697836SJohn.Forte@Sun.COM 	}
50707836SJohn.Forte@Sun.COM 	bzero(&targetState, sizeof (targetState));
50717836SJohn.Forte@Sun.COM 
50727836SJohn.Forte@Sun.COM 	targetState.state = STMF_STATE_ONLINE;
50737836SJohn.Forte@Sun.COM 	targetState.ident[IDENT_LENGTH_BYTE] = devid->identLength;
50747836SJohn.Forte@Sun.COM 	bcopy(&(devid->ident), &targetState.ident[IDENT_LENGTH_BYTE + 1],
50757836SJohn.Forte@Sun.COM 	    devid->identLength);
50767836SJohn.Forte@Sun.COM 	/*
50777836SJohn.Forte@Sun.COM 	 * Open control node for stmf
50787836SJohn.Forte@Sun.COM 	 * to make call to setStmfState()
50797836SJohn.Forte@Sun.COM 	 */
50807836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
50817836SJohn.Forte@Sun.COM 		return (ret);
50827836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &targetState, TARGET_TYPE);
50837836SJohn.Forte@Sun.COM 	(void) close(fd);
50847836SJohn.Forte@Sun.COM 	return (ret);
50857836SJohn.Forte@Sun.COM }
50867836SJohn.Forte@Sun.COM 
50877836SJohn.Forte@Sun.COM /*
50887836SJohn.Forte@Sun.COM  * stmfOnlineLogicalUnit
50897836SJohn.Forte@Sun.COM  *
50907836SJohn.Forte@Sun.COM  * Purpose: Change state of logical unit to online
50917836SJohn.Forte@Sun.COM  *
50927836SJohn.Forte@Sun.COM  * lu - guid of the logical unit to online
50937836SJohn.Forte@Sun.COM  */
50947836SJohn.Forte@Sun.COM int
50957836SJohn.Forte@Sun.COM stmfOnlineLogicalUnit(stmfGuid *lu)
50967836SJohn.Forte@Sun.COM {
50977836SJohn.Forte@Sun.COM 	stmf_state_desc_t luState;
50987836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
50997836SJohn.Forte@Sun.COM 	int fd;
51007836SJohn.Forte@Sun.COM 
51017836SJohn.Forte@Sun.COM 	if (lu == NULL) {
51027836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
51037836SJohn.Forte@Sun.COM 	}
51047836SJohn.Forte@Sun.COM 
51057836SJohn.Forte@Sun.COM 	bzero(&luState, sizeof (luState));
51067836SJohn.Forte@Sun.COM 
51077836SJohn.Forte@Sun.COM 	luState.state = STMF_STATE_ONLINE;
51087836SJohn.Forte@Sun.COM 	bcopy(lu, &luState.ident, sizeof (stmfGuid));
51097836SJohn.Forte@Sun.COM 	/*
51107836SJohn.Forte@Sun.COM 	 * Open control node for stmf
51117836SJohn.Forte@Sun.COM 	 * to make call to setStmfState()
51127836SJohn.Forte@Sun.COM 	 */
51137836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
51147836SJohn.Forte@Sun.COM 		return (ret);
51157836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &luState, LOGICAL_UNIT_TYPE);
51167836SJohn.Forte@Sun.COM 	(void) close(fd);
51177836SJohn.Forte@Sun.COM 	return (ret);
51187836SJohn.Forte@Sun.COM }
51197836SJohn.Forte@Sun.COM 
51207836SJohn.Forte@Sun.COM /*
51217836SJohn.Forte@Sun.COM  * stmfRemoveFromHostGroup
51227836SJohn.Forte@Sun.COM  *
51237836SJohn.Forte@Sun.COM  * Purpose: Removes an initiator from an initiator group
51247836SJohn.Forte@Sun.COM  *
51257836SJohn.Forte@Sun.COM  * hostGroupName - name of an initiator group
51267836SJohn.Forte@Sun.COM  * hostName - name of host group member to remove
51277836SJohn.Forte@Sun.COM  */
51287836SJohn.Forte@Sun.COM int
51297836SJohn.Forte@Sun.COM stmfRemoveFromHostGroup(stmfGroupName *hostGroupName, stmfDevid *hostName)
51307836SJohn.Forte@Sun.COM {
51317836SJohn.Forte@Sun.COM 	int ret;
51327836SJohn.Forte@Sun.COM 	int fd;
51337836SJohn.Forte@Sun.COM 
51347836SJohn.Forte@Sun.COM 	if (hostGroupName == NULL ||
51357836SJohn.Forte@Sun.COM 	    (strnlen((char *)hostGroupName, sizeof (stmfGroupName))
51367836SJohn.Forte@Sun.COM 	    == sizeof (stmfGroupName)) || hostName == NULL) {
51377836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
51387836SJohn.Forte@Sun.COM 	}
51397836SJohn.Forte@Sun.COM 
51407836SJohn.Forte@Sun.COM 	/* call init */
51417836SJohn.Forte@Sun.COM 	ret = initializeConfig();
51427836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
51437836SJohn.Forte@Sun.COM 		return (ret);
51447836SJohn.Forte@Sun.COM 	}
51457836SJohn.Forte@Sun.COM 
51467836SJohn.Forte@Sun.COM 	/*
51477836SJohn.Forte@Sun.COM 	 * Open control node for stmf
51487836SJohn.Forte@Sun.COM 	 */
51497836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
51507836SJohn.Forte@Sun.COM 		return (ret);
51517836SJohn.Forte@Sun.COM 
51527836SJohn.Forte@Sun.COM 	if ((ret = groupMemberIoctl(fd, STMF_IOCTL_REMOVE_HG_ENTRY,
51537836SJohn.Forte@Sun.COM 	    hostGroupName, hostName)) != STMF_STATUS_SUCCESS) {
51547836SJohn.Forte@Sun.COM 		goto done;
51557836SJohn.Forte@Sun.COM 	}
51567836SJohn.Forte@Sun.COM 
51579585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
51589585STim.Szeto@Sun.COM 		goto done;
51599585STim.Szeto@Sun.COM 	}
51609585STim.Szeto@Sun.COM 
51617836SJohn.Forte@Sun.COM 	ret = psRemoveHostGroupMember((char *)hostGroupName,
51627836SJohn.Forte@Sun.COM 	    (char *)hostName->ident);
51637836SJohn.Forte@Sun.COM 	switch (ret) {
51647836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
51657836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
51667836SJohn.Forte@Sun.COM 			break;
51677836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_MEMBER_NOT_FOUND:
51687836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_MEMBER_NOT_FOUND;
51697836SJohn.Forte@Sun.COM 			break;
51707836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_GROUP_NOT_FOUND:
51717836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_GROUP_NOT_FOUND;
51727836SJohn.Forte@Sun.COM 			break;
51737836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
51747836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
51757836SJohn.Forte@Sun.COM 			break;
51767836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
51777836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
51787836SJohn.Forte@Sun.COM 			break;
51797836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
51807836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
51817836SJohn.Forte@Sun.COM 			break;
51827836SJohn.Forte@Sun.COM 		default:
51837836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
51847836SJohn.Forte@Sun.COM 			    "stmfRemoveFromHostGroup"
51857836SJohn.Forte@Sun.COM 			    "psRemoveHostGroupMember:error(%d)", ret);
51867836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
51877836SJohn.Forte@Sun.COM 			break;
51887836SJohn.Forte@Sun.COM 	}
51897836SJohn.Forte@Sun.COM 
51907836SJohn.Forte@Sun.COM done:
51917836SJohn.Forte@Sun.COM 	(void) close(fd);
51927836SJohn.Forte@Sun.COM 	return (ret);
51937836SJohn.Forte@Sun.COM }
51947836SJohn.Forte@Sun.COM 
51957836SJohn.Forte@Sun.COM /*
51967836SJohn.Forte@Sun.COM  * stmfRemoveFromTargetGroup
51977836SJohn.Forte@Sun.COM  *
51987836SJohn.Forte@Sun.COM  * Purpose: Removes a local port from a local port group
51997836SJohn.Forte@Sun.COM  *
52007836SJohn.Forte@Sun.COM  * targetGroupName - name of a target group
52017836SJohn.Forte@Sun.COM  * targetName - name of target to remove
52027836SJohn.Forte@Sun.COM  */
52037836SJohn.Forte@Sun.COM int
52047836SJohn.Forte@Sun.COM stmfRemoveFromTargetGroup(stmfGroupName *targetGroupName, stmfDevid *targetName)
52057836SJohn.Forte@Sun.COM {
52067836SJohn.Forte@Sun.COM 	int ret;
52077836SJohn.Forte@Sun.COM 	int fd;
52087836SJohn.Forte@Sun.COM 
52097836SJohn.Forte@Sun.COM 	if (targetGroupName == NULL ||
52107836SJohn.Forte@Sun.COM 	    (strnlen((char *)targetGroupName, sizeof (stmfGroupName))
52117836SJohn.Forte@Sun.COM 	    == sizeof (stmfGroupName)) || targetName == NULL) {
52127836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
52137836SJohn.Forte@Sun.COM 	}
52147836SJohn.Forte@Sun.COM 
52157836SJohn.Forte@Sun.COM 	/* call init */
52167836SJohn.Forte@Sun.COM 	ret = initializeConfig();
52177836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
52187836SJohn.Forte@Sun.COM 		return (ret);
52197836SJohn.Forte@Sun.COM 	}
52207836SJohn.Forte@Sun.COM 
52217836SJohn.Forte@Sun.COM 	/*
52227836SJohn.Forte@Sun.COM 	 * Open control node for stmf
52237836SJohn.Forte@Sun.COM 	 */
52247836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
52257836SJohn.Forte@Sun.COM 		return (ret);
52267836SJohn.Forte@Sun.COM 
52277836SJohn.Forte@Sun.COM 	if ((ret = groupMemberIoctl(fd, STMF_IOCTL_REMOVE_TG_ENTRY,
52287836SJohn.Forte@Sun.COM 	    targetGroupName, targetName)) != STMF_STATUS_SUCCESS) {
52297836SJohn.Forte@Sun.COM 		goto done;
52307836SJohn.Forte@Sun.COM 	}
52317836SJohn.Forte@Sun.COM 
52329585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
52339585STim.Szeto@Sun.COM 		goto done;
52349585STim.Szeto@Sun.COM 	}
52359585STim.Szeto@Sun.COM 
52367836SJohn.Forte@Sun.COM 	ret = psRemoveTargetGroupMember((char *)targetGroupName,
52377836SJohn.Forte@Sun.COM 	    (char *)targetName->ident);
52387836SJohn.Forte@Sun.COM 	switch (ret) {
52397836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
52407836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
52417836SJohn.Forte@Sun.COM 			break;
52427836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_MEMBER_NOT_FOUND:
52437836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_MEMBER_NOT_FOUND;
52447836SJohn.Forte@Sun.COM 			break;
52457836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_GROUP_NOT_FOUND:
52467836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_GROUP_NOT_FOUND;
52477836SJohn.Forte@Sun.COM 			break;
52487836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
52497836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
52507836SJohn.Forte@Sun.COM 			break;
52517836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
52527836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
52537836SJohn.Forte@Sun.COM 			break;
52547836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
52557836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
52567836SJohn.Forte@Sun.COM 			break;
52577836SJohn.Forte@Sun.COM 		default:
52587836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
52597836SJohn.Forte@Sun.COM 			    "stmfRemoveFromTargetGroup"
52607836SJohn.Forte@Sun.COM 			    "psRemoveTargetGroupMember:error(%d)", ret);
52617836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
52627836SJohn.Forte@Sun.COM 			break;
52637836SJohn.Forte@Sun.COM 	}
52647836SJohn.Forte@Sun.COM 
52657836SJohn.Forte@Sun.COM done:
52667836SJohn.Forte@Sun.COM 	(void) close(fd);
52677836SJohn.Forte@Sun.COM 	return (ret);
52687836SJohn.Forte@Sun.COM }
52697836SJohn.Forte@Sun.COM 
52707836SJohn.Forte@Sun.COM /*
52717836SJohn.Forte@Sun.COM  * stmfRemoveViewEntry
52727836SJohn.Forte@Sun.COM  *
52737836SJohn.Forte@Sun.COM  * Purpose: Removes a view entry from a logical unit
52747836SJohn.Forte@Sun.COM  *
52757836SJohn.Forte@Sun.COM  * lu - guid of lu for which view entry is being removed
52767836SJohn.Forte@Sun.COM  * viewEntryIndex - index of view entry to remove
52777836SJohn.Forte@Sun.COM  *
52787836SJohn.Forte@Sun.COM  */
52797836SJohn.Forte@Sun.COM int
52807836SJohn.Forte@Sun.COM stmfRemoveViewEntry(stmfGuid *lu, uint32_t viewEntryIndex)
52817836SJohn.Forte@Sun.COM {
52827836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
52837836SJohn.Forte@Sun.COM 	int fd;
52847836SJohn.Forte@Sun.COM 	int ioctlRet;
52857836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
52867836SJohn.Forte@Sun.COM 	stmf_view_op_entry_t ioctlViewEntry;
52877836SJohn.Forte@Sun.COM 
52887836SJohn.Forte@Sun.COM 	if (lu == NULL) {
52897836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
52907836SJohn.Forte@Sun.COM 	}
52917836SJohn.Forte@Sun.COM 
52927836SJohn.Forte@Sun.COM 	/* call init */
52937836SJohn.Forte@Sun.COM 	ret = initializeConfig();
52947836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
52957836SJohn.Forte@Sun.COM 		return (ret);
52967836SJohn.Forte@Sun.COM 	}
52977836SJohn.Forte@Sun.COM 
52987836SJohn.Forte@Sun.COM 	/*
52997836SJohn.Forte@Sun.COM 	 * Open control node for stmf
53007836SJohn.Forte@Sun.COM 	 */
53017836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
53027836SJohn.Forte@Sun.COM 		return (ret);
53037836SJohn.Forte@Sun.COM 
53047836SJohn.Forte@Sun.COM 	bzero(&ioctlViewEntry, sizeof (ioctlViewEntry));
53057836SJohn.Forte@Sun.COM 	ioctlViewEntry.ve_ndx_valid = B_TRUE;
53067836SJohn.Forte@Sun.COM 	ioctlViewEntry.ve_ndx = viewEntryIndex;
53077836SJohn.Forte@Sun.COM 	bcopy(lu, &ioctlViewEntry.ve_guid, sizeof (stmfGuid));
53087836SJohn.Forte@Sun.COM 
53097836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
53107836SJohn.Forte@Sun.COM 	/*
53117836SJohn.Forte@Sun.COM 	 * Issue ioctl to add to the view entry
53127836SJohn.Forte@Sun.COM 	 */
53137836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
53147836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry);
53157836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry;
53167836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_REMOVE_VIEW_ENTRY, &stmfIoctl);
53177836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
53187836SJohn.Forte@Sun.COM 		switch (errno) {
53197836SJohn.Forte@Sun.COM 			case EBUSY:
53207836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
53217836SJohn.Forte@Sun.COM 				break;
53229585STim.Szeto@Sun.COM 			case EPERM:
53239585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
53249585STim.Szeto@Sun.COM 				break;
53257836SJohn.Forte@Sun.COM 			case EACCES:
53267836SJohn.Forte@Sun.COM 				switch (stmfIoctl.stmf_error) {
53277836SJohn.Forte@Sun.COM 					case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
53287836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_CONFIG_NONE;
53297836SJohn.Forte@Sun.COM 						break;
53307836SJohn.Forte@Sun.COM 					default:
53317836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_PERM;
53327836SJohn.Forte@Sun.COM 						break;
53337836SJohn.Forte@Sun.COM 				}
53347836SJohn.Forte@Sun.COM 				break;
53357836SJohn.Forte@Sun.COM 			case ENODEV:
53367836SJohn.Forte@Sun.COM 			case ENOENT:
53377836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
53387836SJohn.Forte@Sun.COM 				break;
53397836SJohn.Forte@Sun.COM 			default:
53407836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
53417836SJohn.Forte@Sun.COM 				    "stmfRemoveViewEntry:ioctl errno(%d)",
53427836SJohn.Forte@Sun.COM 				    errno);
53437836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
53447836SJohn.Forte@Sun.COM 				break;
53457836SJohn.Forte@Sun.COM 		}
53467836SJohn.Forte@Sun.COM 		goto done;
53477836SJohn.Forte@Sun.COM 	}
53487836SJohn.Forte@Sun.COM 
53499585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
53509585STim.Szeto@Sun.COM 		goto done;
53519585STim.Szeto@Sun.COM 	}
53529585STim.Szeto@Sun.COM 
53537836SJohn.Forte@Sun.COM 	ret = psRemoveViewEntry(lu, viewEntryIndex);
53547836SJohn.Forte@Sun.COM 	switch (ret) {
53557836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
53567836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
53577836SJohn.Forte@Sun.COM 			break;
53587836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
53597836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
53607836SJohn.Forte@Sun.COM 			break;
53617836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
53627836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
53637836SJohn.Forte@Sun.COM 			break;
53647836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
53657836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
53667836SJohn.Forte@Sun.COM 			break;
53677836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
53687836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
53697836SJohn.Forte@Sun.COM 			break;
53707836SJohn.Forte@Sun.COM 		default:
53717836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
53727836SJohn.Forte@Sun.COM 			    "stmfRemoveViewEntry" "psRemoveViewEntry:error(%d)",
53737836SJohn.Forte@Sun.COM 			    ret);
53747836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
53757836SJohn.Forte@Sun.COM 			break;
53767836SJohn.Forte@Sun.COM 	}
53777836SJohn.Forte@Sun.COM 
53787836SJohn.Forte@Sun.COM done:
53797836SJohn.Forte@Sun.COM 	(void) close(fd);
53807836SJohn.Forte@Sun.COM 	return (ret);
53817836SJohn.Forte@Sun.COM }
53827836SJohn.Forte@Sun.COM 
53837836SJohn.Forte@Sun.COM /*
53847836SJohn.Forte@Sun.COM  * stmfSetProviderData
53857836SJohn.Forte@Sun.COM  *
53867836SJohn.Forte@Sun.COM  * Purpose: set the provider data
53877836SJohn.Forte@Sun.COM  *
53887836SJohn.Forte@Sun.COM  * providerName - unique name of provider
53897836SJohn.Forte@Sun.COM  * nvl - nvlist to set
53907836SJohn.Forte@Sun.COM  * providerType - type of provider for which to set data
53917836SJohn.Forte@Sun.COM  *		STMF_LU_PROVIDER_TYPE
53927836SJohn.Forte@Sun.COM  *		STMF_PORT_PROVIDER_TYPE
53937836SJohn.Forte@Sun.COM  */
53947836SJohn.Forte@Sun.COM int
53957836SJohn.Forte@Sun.COM stmfSetProviderData(char *providerName, nvlist_t *nvl, int providerType)
53967836SJohn.Forte@Sun.COM {
53977836SJohn.Forte@Sun.COM 	return (stmfSetProviderDataProt(providerName, nvl, providerType,
53987836SJohn.Forte@Sun.COM 	    NULL));
53997836SJohn.Forte@Sun.COM }
54007836SJohn.Forte@Sun.COM 
54017836SJohn.Forte@Sun.COM /*
54027836SJohn.Forte@Sun.COM  * stmfSetProviderDataProt
54037836SJohn.Forte@Sun.COM  *
54047836SJohn.Forte@Sun.COM  * Purpose: set the provider data
54057836SJohn.Forte@Sun.COM  *
54067836SJohn.Forte@Sun.COM  * providerName - unique name of provider
54077836SJohn.Forte@Sun.COM  * nvl - nvlist to set
54087836SJohn.Forte@Sun.COM  * providerType - type of provider for which to set data
54097836SJohn.Forte@Sun.COM  *		STMF_LU_PROVIDER_TYPE
54107836SJohn.Forte@Sun.COM  *		STMF_PORT_PROVIDER_TYPE
54117836SJohn.Forte@Sun.COM  * setToken - Stale data token returned in the stmfGetProviderDataProt()
54127836SJohn.Forte@Sun.COM  *	      call or NULL.
54137836SJohn.Forte@Sun.COM  */
54147836SJohn.Forte@Sun.COM int
54157836SJohn.Forte@Sun.COM stmfSetProviderDataProt(char *providerName, nvlist_t *nvl, int providerType,
54167836SJohn.Forte@Sun.COM     uint64_t *setToken)
54177836SJohn.Forte@Sun.COM {
54187836SJohn.Forte@Sun.COM 	int ret;
54197836SJohn.Forte@Sun.COM 	int fd;
54207836SJohn.Forte@Sun.COM 
54217836SJohn.Forte@Sun.COM 	if (providerName == NULL || nvl == NULL) {
54227836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
54237836SJohn.Forte@Sun.COM 	}
54247836SJohn.Forte@Sun.COM 
54257836SJohn.Forte@Sun.COM 	if (providerType != STMF_LU_PROVIDER_TYPE &&
54267836SJohn.Forte@Sun.COM 	    providerType != STMF_PORT_PROVIDER_TYPE) {
54277836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
54287836SJohn.Forte@Sun.COM 	}
54297836SJohn.Forte@Sun.COM 
54307836SJohn.Forte@Sun.COM 	/* call init */
54317836SJohn.Forte@Sun.COM 	ret = initializeConfig();
54327836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
54337836SJohn.Forte@Sun.COM 		return (ret);
54347836SJohn.Forte@Sun.COM 	}
54357836SJohn.Forte@Sun.COM 
54367836SJohn.Forte@Sun.COM 	/*
54377836SJohn.Forte@Sun.COM 	 * Open control node for stmf
54387836SJohn.Forte@Sun.COM 	 */
54397836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
54407836SJohn.Forte@Sun.COM 		return (ret);
54417836SJohn.Forte@Sun.COM 
54429585STim.Szeto@Sun.COM 	ret = setProviderData(fd, providerName, nvl, providerType, setToken);
54437836SJohn.Forte@Sun.COM 
54447836SJohn.Forte@Sun.COM 	(void) close(fd);
54457836SJohn.Forte@Sun.COM 
54467836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
54477836SJohn.Forte@Sun.COM 		goto done;
54487836SJohn.Forte@Sun.COM 	}
54497836SJohn.Forte@Sun.COM 
54509585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
54519585STim.Szeto@Sun.COM 		goto done;
54529585STim.Szeto@Sun.COM 	}
54539585STim.Szeto@Sun.COM 
54547836SJohn.Forte@Sun.COM 	/* setting driver provider data successful. Now persist it */
54559585STim.Szeto@Sun.COM 	ret = psSetProviderData(providerName, nvl, providerType, NULL);
54567836SJohn.Forte@Sun.COM 	switch (ret) {
54577836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
54587836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
54597836SJohn.Forte@Sun.COM 			break;
54607836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_EXISTS:
54617836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_EXISTS;
54627836SJohn.Forte@Sun.COM 			break;
54637836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
54647836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
54657836SJohn.Forte@Sun.COM 			break;
54667836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
54677836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
54687836SJohn.Forte@Sun.COM 			break;
54697836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
54707836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
54717836SJohn.Forte@Sun.COM 			break;
54727836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_PROV_DATA_STALE:
54737836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_PROV_DATA_STALE;
54747836SJohn.Forte@Sun.COM 			break;
54757836SJohn.Forte@Sun.COM 		default:
54767836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
54777836SJohn.Forte@Sun.COM 			    "stmfSetProviderData"
54787836SJohn.Forte@Sun.COM 			    "psSetProviderData:error(%d)", ret);
54797836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
54807836SJohn.Forte@Sun.COM 			break;
54817836SJohn.Forte@Sun.COM 	}
54827836SJohn.Forte@Sun.COM 
54837836SJohn.Forte@Sun.COM done:
54847836SJohn.Forte@Sun.COM 	return (ret);
54857836SJohn.Forte@Sun.COM }
54867836SJohn.Forte@Sun.COM 
54877836SJohn.Forte@Sun.COM /*
54889585STim.Szeto@Sun.COM  * getProviderData
54899585STim.Szeto@Sun.COM  *
54909585STim.Szeto@Sun.COM  * Purpose: set the provider data from stmf
54919585STim.Szeto@Sun.COM  *
54929585STim.Szeto@Sun.COM  * providerName - unique name of provider
54939585STim.Szeto@Sun.COM  * nvl - nvlist to load/retrieve
54949585STim.Szeto@Sun.COM  * providerType - logical unit or port provider
54959585STim.Szeto@Sun.COM  * setToken - returned stale data token
54969585STim.Szeto@Sun.COM  */
54979585STim.Szeto@Sun.COM int
54989585STim.Szeto@Sun.COM getProviderData(char *providerName, nvlist_t **nvl, int providerType,
54999585STim.Szeto@Sun.COM     uint64_t *setToken)
55009585STim.Szeto@Sun.COM {
55019585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
55029585STim.Szeto@Sun.COM 	int fd;
55039585STim.Szeto@Sun.COM 	int ioctlRet;
55049585STim.Szeto@Sun.COM 	size_t nvlistSize = ALLOC_PP_DATA_SIZE;
55059585STim.Szeto@Sun.COM 	int retryCnt = 0;
55069585STim.Szeto@Sun.COM 	int retryCntMax = MAX_PROVIDER_RETRY;
55079585STim.Szeto@Sun.COM 	stmf_ppioctl_data_t ppi = {0}, *ppi_out = NULL;
55089585STim.Szeto@Sun.COM 	boolean_t retry = B_TRUE;
55099585STim.Szeto@Sun.COM 	stmf_iocdata_t stmfIoctl;
55109585STim.Szeto@Sun.COM 
55119585STim.Szeto@Sun.COM 	if (providerName == NULL) {
55129585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
55139585STim.Szeto@Sun.COM 	}
55149585STim.Szeto@Sun.COM 
55159585STim.Szeto@Sun.COM 	/*
55169585STim.Szeto@Sun.COM 	 * Open control node for stmf
55179585STim.Szeto@Sun.COM 	 */
55189585STim.Szeto@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
55199585STim.Szeto@Sun.COM 		return (ret);
55209585STim.Szeto@Sun.COM 
55219585STim.Szeto@Sun.COM 	/* set provider name and provider type */
55229585STim.Szeto@Sun.COM 	if (strlcpy(ppi.ppi_name, providerName,
55239585STim.Szeto@Sun.COM 	    sizeof (ppi.ppi_name)) >=
55249585STim.Szeto@Sun.COM 	    sizeof (ppi.ppi_name)) {
55259585STim.Szeto@Sun.COM 		ret = STMF_ERROR_INVALID_ARG;
55269585STim.Szeto@Sun.COM 		goto done;
55279585STim.Szeto@Sun.COM 	}
55289585STim.Szeto@Sun.COM 	switch (providerType) {
55299585STim.Szeto@Sun.COM 		case STMF_LU_PROVIDER_TYPE:
55309585STim.Szeto@Sun.COM 			ppi.ppi_lu_provider = 1;
55319585STim.Szeto@Sun.COM 			break;
55329585STim.Szeto@Sun.COM 		case STMF_PORT_PROVIDER_TYPE:
55339585STim.Szeto@Sun.COM 			ppi.ppi_port_provider = 1;
55349585STim.Szeto@Sun.COM 			break;
55359585STim.Szeto@Sun.COM 		default:
55369585STim.Szeto@Sun.COM 			ret = STMF_ERROR_INVALID_ARG;
55379585STim.Szeto@Sun.COM 			goto done;
55389585STim.Szeto@Sun.COM 	}
55399585STim.Szeto@Sun.COM 
55409585STim.Szeto@Sun.COM 	do {
55419585STim.Szeto@Sun.COM 		/* allocate memory for ioctl */
55429585STim.Szeto@Sun.COM 		ppi_out = (stmf_ppioctl_data_t *)calloc(1, nvlistSize +
55439585STim.Szeto@Sun.COM 		    sizeof (stmf_ppioctl_data_t));
55449585STim.Szeto@Sun.COM 		if (ppi_out == NULL) {
55459585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NOMEM;
55469585STim.Szeto@Sun.COM 			goto done;
55479585STim.Szeto@Sun.COM 
55489585STim.Szeto@Sun.COM 		}
55499585STim.Szeto@Sun.COM 
55509585STim.Szeto@Sun.COM 		/* set the size of the ioctl data to allocated buffer */
55519585STim.Szeto@Sun.COM 		ppi.ppi_data_size = nvlistSize;
55529585STim.Szeto@Sun.COM 
55539585STim.Szeto@Sun.COM 		bzero(&stmfIoctl, sizeof (stmfIoctl));
55549585STim.Szeto@Sun.COM 
55559585STim.Szeto@Sun.COM 		stmfIoctl.stmf_version = STMF_VERSION_1;
55569585STim.Szeto@Sun.COM 		stmfIoctl.stmf_ibuf_size = sizeof (stmf_ppioctl_data_t);
55579585STim.Szeto@Sun.COM 		stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ppi;
55589585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf_size = sizeof (stmf_ppioctl_data_t) +
55599585STim.Szeto@Sun.COM 		    nvlistSize;
55609585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)ppi_out;
55619585STim.Szeto@Sun.COM 		ioctlRet = ioctl(fd, STMF_IOCTL_GET_PP_DATA, &stmfIoctl);
55629585STim.Szeto@Sun.COM 		if (ioctlRet != 0) {
55639585STim.Szeto@Sun.COM 			switch (errno) {
55649585STim.Szeto@Sun.COM 				case EBUSY:
55659585STim.Szeto@Sun.COM 					ret = STMF_ERROR_BUSY;
55669585STim.Szeto@Sun.COM 					break;
55679585STim.Szeto@Sun.COM 				case EPERM:
55689585STim.Szeto@Sun.COM 				case EACCES:
55699585STim.Szeto@Sun.COM 					ret = STMF_ERROR_PERM;
55709585STim.Szeto@Sun.COM 					break;
55719585STim.Szeto@Sun.COM 				case EINVAL:
55729585STim.Szeto@Sun.COM 					if (stmfIoctl.stmf_error ==
55739585STim.Szeto@Sun.COM 					    STMF_IOCERR_INSUFFICIENT_BUF) {
55749585STim.Szeto@Sun.COM 						nvlistSize =
55759585STim.Szeto@Sun.COM 						    ppi_out->ppi_data_size;
55769585STim.Szeto@Sun.COM 						free(ppi_out);
55779585STim.Szeto@Sun.COM 						ppi_out = NULL;
55789585STim.Szeto@Sun.COM 						if (retryCnt++ > retryCntMax) {
55799585STim.Szeto@Sun.COM 							retry = B_FALSE;
55809585STim.Szeto@Sun.COM 							ret = STMF_ERROR_BUSY;
55819585STim.Szeto@Sun.COM 						} else {
55829585STim.Szeto@Sun.COM 							ret =
55839585STim.Szeto@Sun.COM 							    STMF_STATUS_SUCCESS;
55849585STim.Szeto@Sun.COM 						}
55859585STim.Szeto@Sun.COM 					} else {
55869585STim.Szeto@Sun.COM 						syslog(LOG_DEBUG,
55879585STim.Szeto@Sun.COM 						    "getProviderData:ioctl"
55889585STim.Szeto@Sun.COM 						    "unable to retrieve "
55899585STim.Szeto@Sun.COM 						    "nvlist");
55909585STim.Szeto@Sun.COM 						ret = STMF_STATUS_ERROR;
55919585STim.Szeto@Sun.COM 					}
55929585STim.Szeto@Sun.COM 					break;
55939585STim.Szeto@Sun.COM 				case ENOENT:
55949585STim.Szeto@Sun.COM 					ret = STMF_ERROR_NOT_FOUND;
55959585STim.Szeto@Sun.COM 					break;
55969585STim.Szeto@Sun.COM 				default:
55979585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
55989585STim.Szeto@Sun.COM 					    "getProviderData:ioctl errno(%d)",
55999585STim.Szeto@Sun.COM 					    errno);
56009585STim.Szeto@Sun.COM 					ret = STMF_STATUS_ERROR;
56019585STim.Szeto@Sun.COM 					break;
56029585STim.Szeto@Sun.COM 			}
56039585STim.Szeto@Sun.COM 			if (ret != STMF_STATUS_SUCCESS)
56049585STim.Szeto@Sun.COM 				goto done;
56059585STim.Szeto@Sun.COM 		}
56069585STim.Szeto@Sun.COM 	} while (retry && stmfIoctl.stmf_error == STMF_IOCERR_INSUFFICIENT_BUF);
56079585STim.Szeto@Sun.COM 
56089585STim.Szeto@Sun.COM 	if ((ret = nvlist_unpack((char *)ppi_out->ppi_data,
56099585STim.Szeto@Sun.COM 	    ppi_out->ppi_data_size, nvl, 0)) != 0) {
56109585STim.Szeto@Sun.COM 		ret = STMF_STATUS_ERROR;
56119585STim.Szeto@Sun.COM 		goto done;
56129585STim.Szeto@Sun.COM 	}
56139585STim.Szeto@Sun.COM 
56149585STim.Szeto@Sun.COM 	/* caller has asked for new token */
56159585STim.Szeto@Sun.COM 	if (setToken) {
56169585STim.Szeto@Sun.COM 		*setToken = ppi_out->ppi_token;
56179585STim.Szeto@Sun.COM 	}
56189585STim.Szeto@Sun.COM done:
56199585STim.Szeto@Sun.COM 	free(ppi_out);
56209585STim.Szeto@Sun.COM 	(void) close(fd);
56219585STim.Szeto@Sun.COM 	return (ret);
56229585STim.Szeto@Sun.COM }
56239585STim.Szeto@Sun.COM 
56249585STim.Szeto@Sun.COM /*
56257836SJohn.Forte@Sun.COM  * setProviderData
56267836SJohn.Forte@Sun.COM  *
56279585STim.Szeto@Sun.COM  * Purpose: set the provider data in stmf
56287836SJohn.Forte@Sun.COM  *
56297836SJohn.Forte@Sun.COM  * providerName - unique name of provider
56307836SJohn.Forte@Sun.COM  * nvl - nvlist to set
56317836SJohn.Forte@Sun.COM  * providerType - logical unit or port provider
56329585STim.Szeto@Sun.COM  * setToken - stale data token to check if not NULL
56337836SJohn.Forte@Sun.COM  */
56347836SJohn.Forte@Sun.COM static int
56359585STim.Szeto@Sun.COM setProviderData(int fd, char *providerName, nvlist_t *nvl, int providerType,
56369585STim.Szeto@Sun.COM     uint64_t *setToken)
56377836SJohn.Forte@Sun.COM {
56387836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
56397836SJohn.Forte@Sun.COM 	int ioctlRet;
56407836SJohn.Forte@Sun.COM 	size_t nvlistEncodedSize;
56417836SJohn.Forte@Sun.COM 	stmf_ppioctl_data_t *ppi = NULL;
56429585STim.Szeto@Sun.COM 	uint64_t outToken;
56437836SJohn.Forte@Sun.COM 	char *allocatedNvBuffer;
56447836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
56457836SJohn.Forte@Sun.COM 
56467836SJohn.Forte@Sun.COM 	if (providerName == NULL) {
56477836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
56487836SJohn.Forte@Sun.COM 	}
56497836SJohn.Forte@Sun.COM 
56507836SJohn.Forte@Sun.COM 	/* get size of encoded nvlist */
56517836SJohn.Forte@Sun.COM 	if (nvlist_size(nvl, &nvlistEncodedSize, NV_ENCODE_XDR) != 0) {
56527836SJohn.Forte@Sun.COM 		return (STMF_STATUS_ERROR);
56537836SJohn.Forte@Sun.COM 	}
56547836SJohn.Forte@Sun.COM 
56557836SJohn.Forte@Sun.COM 	/* allocate memory for ioctl */
56567836SJohn.Forte@Sun.COM 	ppi = (stmf_ppioctl_data_t *)calloc(1, nvlistEncodedSize +
56577836SJohn.Forte@Sun.COM 	    sizeof (stmf_ppioctl_data_t));
56587836SJohn.Forte@Sun.COM 	if (ppi == NULL) {
56597836SJohn.Forte@Sun.COM 		return (STMF_ERROR_NOMEM);
56607836SJohn.Forte@Sun.COM 	}
56617836SJohn.Forte@Sun.COM 
56629585STim.Szeto@Sun.COM 	if (setToken) {
56639585STim.Szeto@Sun.COM 		ppi->ppi_token_valid = 1;
56649585STim.Szeto@Sun.COM 		ppi->ppi_token = *setToken;
56659585STim.Szeto@Sun.COM 	}
56669585STim.Szeto@Sun.COM 
56677836SJohn.Forte@Sun.COM 	allocatedNvBuffer = (char *)&ppi->ppi_data;
56687836SJohn.Forte@Sun.COM 	if (nvlist_pack(nvl, &allocatedNvBuffer, &nvlistEncodedSize,
56697836SJohn.Forte@Sun.COM 	    NV_ENCODE_XDR, 0) != 0) {
56707836SJohn.Forte@Sun.COM 		return (STMF_STATUS_ERROR);
56717836SJohn.Forte@Sun.COM 	}
56727836SJohn.Forte@Sun.COM 
56737836SJohn.Forte@Sun.COM 	/* set provider name and provider type */
56747836SJohn.Forte@Sun.COM 	(void) strncpy(ppi->ppi_name, providerName, sizeof (ppi->ppi_name));
56757836SJohn.Forte@Sun.COM 	switch (providerType) {
56767836SJohn.Forte@Sun.COM 		case STMF_LU_PROVIDER_TYPE:
56777836SJohn.Forte@Sun.COM 			ppi->ppi_lu_provider = 1;
56787836SJohn.Forte@Sun.COM 			break;
56797836SJohn.Forte@Sun.COM 		case STMF_PORT_PROVIDER_TYPE:
56807836SJohn.Forte@Sun.COM 			ppi->ppi_port_provider = 1;
56817836SJohn.Forte@Sun.COM 			break;
56827836SJohn.Forte@Sun.COM 		default:
56837836SJohn.Forte@Sun.COM 			return (STMF_ERROR_INVALID_ARG);
56847836SJohn.Forte@Sun.COM 	}
56857836SJohn.Forte@Sun.COM 
56867836SJohn.Forte@Sun.COM 	/* set the size of the ioctl data to packed data size */
56877836SJohn.Forte@Sun.COM 	ppi->ppi_data_size = nvlistEncodedSize;
56887836SJohn.Forte@Sun.COM 
56897836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
56907836SJohn.Forte@Sun.COM 
56917836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
56927836SJohn.Forte@Sun.COM 	/*
56937836SJohn.Forte@Sun.COM 	 * Subtracting 8 from the size as that is the size of the last member
56947836SJohn.Forte@Sun.COM 	 * of the structure where the packed data resides
56957836SJohn.Forte@Sun.COM 	 */
56967836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = nvlistEncodedSize +
56977836SJohn.Forte@Sun.COM 	    sizeof (stmf_ppioctl_data_t) - 8;
56987836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)ppi;
56999585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf_size = sizeof (uint64_t);
57009585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&outToken;
57017836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_LOAD_PP_DATA, &stmfIoctl);
57027836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
57037836SJohn.Forte@Sun.COM 		switch (errno) {
57047836SJohn.Forte@Sun.COM 			case EBUSY:
57057836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
57067836SJohn.Forte@Sun.COM 				break;
57079585STim.Szeto@Sun.COM 			case EPERM:
57087836SJohn.Forte@Sun.COM 			case EACCES:
57097836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
57107836SJohn.Forte@Sun.COM 				break;
57119585STim.Szeto@Sun.COM 			case EINVAL:
57129585STim.Szeto@Sun.COM 				if (stmfIoctl.stmf_error ==
57139585STim.Szeto@Sun.COM 				    STMF_IOCERR_PPD_UPDATED) {
57149585STim.Szeto@Sun.COM 					ret = STMF_ERROR_PROV_DATA_STALE;
57159585STim.Szeto@Sun.COM 				} else {
57169585STim.Szeto@Sun.COM 					ret = STMF_STATUS_ERROR;
57179585STim.Szeto@Sun.COM 				}
57189585STim.Szeto@Sun.COM 				break;
57197836SJohn.Forte@Sun.COM 			default:
57207836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
57217836SJohn.Forte@Sun.COM 				    "setProviderData:ioctl errno(%d)", errno);
57227836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
57237836SJohn.Forte@Sun.COM 				break;
57247836SJohn.Forte@Sun.COM 		}
57257836SJohn.Forte@Sun.COM 		if (ret != STMF_STATUS_SUCCESS)
57267836SJohn.Forte@Sun.COM 			goto done;
57277836SJohn.Forte@Sun.COM 	}
57287836SJohn.Forte@Sun.COM 
57299585STim.Szeto@Sun.COM 	/* caller has asked for new token */
57309585STim.Szeto@Sun.COM 	if (setToken) {
57319585STim.Szeto@Sun.COM 		*setToken = outToken;
57329585STim.Szeto@Sun.COM 	}
57337836SJohn.Forte@Sun.COM done:
57347836SJohn.Forte@Sun.COM 	free(ppi);
57357836SJohn.Forte@Sun.COM 	return (ret);
57367836SJohn.Forte@Sun.COM }
57379585STim.Szeto@Sun.COM 
57389585STim.Szeto@Sun.COM /*
57399585STim.Szeto@Sun.COM  * set the persistence method in the library only or library and service
57409585STim.Szeto@Sun.COM  */
57419585STim.Szeto@Sun.COM int
57429585STim.Szeto@Sun.COM stmfSetPersistMethod(uint8_t persistType, boolean_t serviceSet)
57439585STim.Szeto@Sun.COM {
57449585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
57459585STim.Szeto@Sun.COM 	int oldPersist;
57469585STim.Szeto@Sun.COM 
57479585STim.Szeto@Sun.COM 	(void) pthread_mutex_lock(&persistenceTypeLock);
57489585STim.Szeto@Sun.COM 	oldPersist = iPersistType;
57499585STim.Szeto@Sun.COM 	if (persistType == STMF_PERSIST_NONE ||
57509585STim.Szeto@Sun.COM 	    persistType == STMF_PERSIST_SMF) {
57519585STim.Szeto@Sun.COM 		iLibSetPersist = B_TRUE;
57529585STim.Szeto@Sun.COM 		iPersistType = persistType;
57539585STim.Szeto@Sun.COM 	} else {
57549585STim.Szeto@Sun.COM 		(void) pthread_mutex_unlock(&persistenceTypeLock);
57559585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
57569585STim.Szeto@Sun.COM 	}
57579585STim.Szeto@Sun.COM 	/* Is this for this library open or in SMF */
57589585STim.Szeto@Sun.COM 	if (serviceSet == B_TRUE) {
57599585STim.Szeto@Sun.COM 		ret = psSetServicePersist(persistType);
57609585STim.Szeto@Sun.COM 		if (ret != STMF_PS_SUCCESS) {
57619585STim.Szeto@Sun.COM 			ret = STMF_ERROR_PERSIST_TYPE;
57629585STim.Szeto@Sun.COM 			/* Set to old value */
57639585STim.Szeto@Sun.COM 			iPersistType = oldPersist;
57649585STim.Szeto@Sun.COM 		}
57659585STim.Szeto@Sun.COM 	}
57669585STim.Szeto@Sun.COM 	(void) pthread_mutex_unlock(&persistenceTypeLock);
57679585STim.Szeto@Sun.COM 
57689585STim.Szeto@Sun.COM 	return (ret);
57699585STim.Szeto@Sun.COM }
57709585STim.Szeto@Sun.COM 
57719585STim.Szeto@Sun.COM /*
57729585STim.Szeto@Sun.COM  * Only returns internal state for persist. If unset, goes to ps. If that
57739585STim.Szeto@Sun.COM  * fails, returns default setting
57749585STim.Szeto@Sun.COM  */
57759585STim.Szeto@Sun.COM static uint8_t
57769585STim.Szeto@Sun.COM iGetPersistMethod()
57779585STim.Szeto@Sun.COM {
57789585STim.Szeto@Sun.COM 
57799585STim.Szeto@Sun.COM 	uint8_t persistType = 0;
57809585STim.Szeto@Sun.COM 
57819585STim.Szeto@Sun.COM 	(void) pthread_mutex_lock(&persistenceTypeLock);
57829585STim.Szeto@Sun.COM 	if (iLibSetPersist) {
57839585STim.Szeto@Sun.COM 		persistType = iPersistType;
57849585STim.Szeto@Sun.COM 	} else {
57859585STim.Szeto@Sun.COM 		int ret;
57869585STim.Szeto@Sun.COM 		ret = psGetServicePersist(&persistType);
57879585STim.Szeto@Sun.COM 		if (ret != STMF_PS_SUCCESS) {
57889585STim.Szeto@Sun.COM 			/* set to default */
57899585STim.Szeto@Sun.COM 			persistType = STMF_DEFAULT_PERSIST;
57909585STim.Szeto@Sun.COM 		}
57919585STim.Szeto@Sun.COM 	}
57929585STim.Szeto@Sun.COM 	(void) pthread_mutex_unlock(&persistenceTypeLock);
57939585STim.Szeto@Sun.COM 	return (persistType);
57949585STim.Szeto@Sun.COM }
57959585STim.Szeto@Sun.COM 
57969585STim.Szeto@Sun.COM /*
57979585STim.Szeto@Sun.COM  * Returns either library state or persistent config state depending on
57989585STim.Szeto@Sun.COM  * serviceState
57999585STim.Szeto@Sun.COM  */
58009585STim.Szeto@Sun.COM int
58019585STim.Szeto@Sun.COM stmfGetPersistMethod(uint8_t *persistType, boolean_t serviceState)
58029585STim.Szeto@Sun.COM {
58039585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
58049585STim.Szeto@Sun.COM 
58059585STim.Szeto@Sun.COM 	if (persistType == NULL) {
58069585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
58079585STim.Szeto@Sun.COM 	}
58089585STim.Szeto@Sun.COM 	if (serviceState) {
58099585STim.Szeto@Sun.COM 		ret = psGetServicePersist(persistType);
58109585STim.Szeto@Sun.COM 		if (ret != STMF_PS_SUCCESS) {
58119585STim.Szeto@Sun.COM 			ret = STMF_ERROR_PERSIST_TYPE;
58129585STim.Szeto@Sun.COM 		}
58139585STim.Szeto@Sun.COM 	} else {
58149585STim.Szeto@Sun.COM 		(void) pthread_mutex_lock(&persistenceTypeLock);
58159585STim.Szeto@Sun.COM 		if (iLibSetPersist) {
58169585STim.Szeto@Sun.COM 			*persistType = iPersistType;
58179585STim.Szeto@Sun.COM 		} else {
58189585STim.Szeto@Sun.COM 			*persistType = STMF_DEFAULT_PERSIST;
58199585STim.Szeto@Sun.COM 		}
58209585STim.Szeto@Sun.COM 		(void) pthread_mutex_unlock(&persistenceTypeLock);
58219585STim.Szeto@Sun.COM 	}
58229585STim.Szeto@Sun.COM 
58239585STim.Szeto@Sun.COM 	return (ret);
58249585STim.Szeto@Sun.COM }
5825*10691STim.Szeto@Sun.COM 
5826*10691STim.Szeto@Sun.COM /*
5827*10691STim.Szeto@Sun.COM  * validateLunNumIoctl
5828*10691STim.Szeto@Sun.COM  *
5829*10691STim.Szeto@Sun.COM  * Purpose: Issues ioctl to check and get available lun# in view entry
5830*10691STim.Szeto@Sun.COM  *
5831*10691STim.Szeto@Sun.COM  * viewEntry - view entry to use
5832*10691STim.Szeto@Sun.COM  */
5833*10691STim.Szeto@Sun.COM static int
5834*10691STim.Szeto@Sun.COM validateLunNumIoctl(int fd, stmfViewEntry *viewEntry)
5835*10691STim.Szeto@Sun.COM {
5836*10691STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
5837*10691STim.Szeto@Sun.COM 	int ioctlRet;
5838*10691STim.Szeto@Sun.COM 	stmf_iocdata_t stmfIoctl;
5839*10691STim.Szeto@Sun.COM 	stmf_view_op_entry_t ioctlViewEntry;
5840*10691STim.Szeto@Sun.COM 
5841*10691STim.Szeto@Sun.COM 	bzero(&ioctlViewEntry, sizeof (ioctlViewEntry));
5842*10691STim.Szeto@Sun.COM 	/*
5843*10691STim.Szeto@Sun.COM 	 * don't set ve_ndx or ve_ndx_valid as ve_ndx_valid should be
5844*10691STim.Szeto@Sun.COM 	 * false on input
5845*10691STim.Szeto@Sun.COM 	 */
5846*10691STim.Szeto@Sun.COM 	ioctlViewEntry.ve_lu_number_valid = viewEntry->luNbrValid;
5847*10691STim.Szeto@Sun.COM 	ioctlViewEntry.ve_all_hosts = viewEntry->allHosts;
5848*10691STim.Szeto@Sun.COM 	ioctlViewEntry.ve_all_targets = viewEntry->allTargets;
5849*10691STim.Szeto@Sun.COM 
5850*10691STim.Szeto@Sun.COM 	if (viewEntry->allHosts == B_FALSE) {
5851*10691STim.Szeto@Sun.COM 		bcopy(viewEntry->hostGroup, &ioctlViewEntry.ve_host_group.name,
5852*10691STim.Szeto@Sun.COM 		    sizeof (stmfGroupName));
5853*10691STim.Szeto@Sun.COM 		ioctlViewEntry.ve_host_group.name_size =
5854*10691STim.Szeto@Sun.COM 		    strlen((char *)viewEntry->hostGroup);
5855*10691STim.Szeto@Sun.COM 	}
5856*10691STim.Szeto@Sun.COM 	if (viewEntry->allTargets == B_FALSE) {
5857*10691STim.Szeto@Sun.COM 		bcopy(viewEntry->targetGroup,
5858*10691STim.Szeto@Sun.COM 		    &ioctlViewEntry.ve_target_group.name,
5859*10691STim.Szeto@Sun.COM 		    sizeof (stmfGroupName));
5860*10691STim.Szeto@Sun.COM 		ioctlViewEntry.ve_target_group.name_size =
5861*10691STim.Szeto@Sun.COM 		    strlen((char *)viewEntry->targetGroup);
5862*10691STim.Szeto@Sun.COM 	}
5863*10691STim.Szeto@Sun.COM 	/* Validating the lun number */
5864*10691STim.Szeto@Sun.COM 	if (viewEntry->luNbrValid) {
5865*10691STim.Szeto@Sun.COM 		bcopy(viewEntry->luNbr, &ioctlViewEntry.ve_lu_nbr,
5866*10691STim.Szeto@Sun.COM 		    sizeof (ioctlViewEntry.ve_lu_nbr));
5867*10691STim.Szeto@Sun.COM 	}
5868*10691STim.Szeto@Sun.COM 
5869*10691STim.Szeto@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
5870*10691STim.Szeto@Sun.COM 	/*
5871*10691STim.Szeto@Sun.COM 	 * Issue ioctl to validate lun# in the view entry
5872*10691STim.Szeto@Sun.COM 	 */
5873*10691STim.Szeto@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
5874*10691STim.Szeto@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry);
5875*10691STim.Szeto@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry;
5876*10691STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf_size = sizeof (ioctlViewEntry);
5877*10691STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&ioctlViewEntry;
5878*10691STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_VALIDATE_VIEW, &stmfIoctl);
5879*10691STim.Szeto@Sun.COM 
5880*10691STim.Szeto@Sun.COM 	/* save available lun number */
5881*10691STim.Szeto@Sun.COM 	if (!viewEntry->luNbrValid) {
5882*10691STim.Szeto@Sun.COM 		bcopy(ioctlViewEntry.ve_lu_nbr, viewEntry->luNbr,
5883*10691STim.Szeto@Sun.COM 		    sizeof (ioctlViewEntry.ve_lu_nbr));
5884*10691STim.Szeto@Sun.COM 	}
5885*10691STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
5886*10691STim.Szeto@Sun.COM 		switch (errno) {
5887*10691STim.Szeto@Sun.COM 			case EBUSY:
5888*10691STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
5889*10691STim.Szeto@Sun.COM 				break;
5890*10691STim.Szeto@Sun.COM 			case EPERM:
5891*10691STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
5892*10691STim.Szeto@Sun.COM 				break;
5893*10691STim.Szeto@Sun.COM 			case EACCES:
5894*10691STim.Szeto@Sun.COM 				switch (stmfIoctl.stmf_error) {
5895*10691STim.Szeto@Sun.COM 					case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
5896*10691STim.Szeto@Sun.COM 						ret = STMF_ERROR_CONFIG_NONE;
5897*10691STim.Szeto@Sun.COM 						break;
5898*10691STim.Szeto@Sun.COM 					default:
5899*10691STim.Szeto@Sun.COM 						ret = STMF_ERROR_PERM;
5900*10691STim.Szeto@Sun.COM 						break;
5901*10691STim.Szeto@Sun.COM 				}
5902*10691STim.Szeto@Sun.COM 				break;
5903*10691STim.Szeto@Sun.COM 			default:
5904*10691STim.Szeto@Sun.COM 				switch (stmfIoctl.stmf_error) {
5905*10691STim.Szeto@Sun.COM 					case STMF_IOCERR_LU_NUMBER_IN_USE:
5906*10691STim.Szeto@Sun.COM 						ret = STMF_ERROR_LUN_IN_USE;
5907*10691STim.Szeto@Sun.COM 						break;
5908*10691STim.Szeto@Sun.COM 					case STMF_IOCERR_VIEW_ENTRY_CONFLICT:
5909*10691STim.Szeto@Sun.COM 						ret = STMF_ERROR_VE_CONFLICT;
5910*10691STim.Szeto@Sun.COM 						break;
5911*10691STim.Szeto@Sun.COM 					case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
5912*10691STim.Szeto@Sun.COM 						ret = STMF_ERROR_CONFIG_NONE;
5913*10691STim.Szeto@Sun.COM 						break;
5914*10691STim.Szeto@Sun.COM 					case STMF_IOCERR_INVALID_HG:
5915*10691STim.Szeto@Sun.COM 						ret = STMF_ERROR_INVALID_HG;
5916*10691STim.Szeto@Sun.COM 						break;
5917*10691STim.Szeto@Sun.COM 					case STMF_IOCERR_INVALID_TG:
5918*10691STim.Szeto@Sun.COM 						ret = STMF_ERROR_INVALID_TG;
5919*10691STim.Szeto@Sun.COM 						break;
5920*10691STim.Szeto@Sun.COM 					default:
5921*10691STim.Szeto@Sun.COM 						syslog(LOG_DEBUG,
5922*10691STim.Szeto@Sun.COM 						    "addViewEntryIoctl"
5923*10691STim.Szeto@Sun.COM 						    ":error(%d)",
5924*10691STim.Szeto@Sun.COM 						    stmfIoctl.stmf_error);
5925*10691STim.Szeto@Sun.COM 						ret = STMF_STATUS_ERROR;
5926*10691STim.Szeto@Sun.COM 						break;
5927*10691STim.Szeto@Sun.COM 				}
5928*10691STim.Szeto@Sun.COM 				break;
5929*10691STim.Szeto@Sun.COM 		}
5930*10691STim.Szeto@Sun.COM 	}
5931*10691STim.Szeto@Sun.COM 	return (ret);
5932*10691STim.Szeto@Sun.COM }
5933*10691STim.Szeto@Sun.COM 
5934*10691STim.Szeto@Sun.COM /*
5935*10691STim.Szeto@Sun.COM  * stmfValidateView
5936*10691STim.Szeto@Sun.COM  *
5937*10691STim.Szeto@Sun.COM  * Purpose: Validate or get lun # base on TG, HG of view entry
5938*10691STim.Szeto@Sun.COM  *
5939*10691STim.Szeto@Sun.COM  * viewEntry - view entry structure to use
5940*10691STim.Szeto@Sun.COM  */
5941*10691STim.Szeto@Sun.COM int
5942*10691STim.Szeto@Sun.COM stmfValidateView(stmfViewEntry *viewEntry)
5943*10691STim.Szeto@Sun.COM {
5944*10691STim.Szeto@Sun.COM 	int ret;
5945*10691STim.Szeto@Sun.COM 	int fd;
5946*10691STim.Szeto@Sun.COM 	stmfViewEntry iViewEntry;
5947*10691STim.Szeto@Sun.COM 
5948*10691STim.Szeto@Sun.COM 	if (viewEntry == NULL) {
5949*10691STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
5950*10691STim.Szeto@Sun.COM 	}
5951*10691STim.Szeto@Sun.COM 
5952*10691STim.Szeto@Sun.COM 	/* initialize and set internal view entry */
5953*10691STim.Szeto@Sun.COM 	bzero(&iViewEntry, sizeof (iViewEntry));
5954*10691STim.Szeto@Sun.COM 
5955*10691STim.Szeto@Sun.COM 	if (!viewEntry->allHosts) {
5956*10691STim.Szeto@Sun.COM 		bcopy(viewEntry->hostGroup, iViewEntry.hostGroup,
5957*10691STim.Szeto@Sun.COM 		    sizeof (iViewEntry.hostGroup));
5958*10691STim.Szeto@Sun.COM 	} else {
5959*10691STim.Szeto@Sun.COM 		iViewEntry.allHosts = B_TRUE;
5960*10691STim.Szeto@Sun.COM 	}
5961*10691STim.Szeto@Sun.COM 
5962*10691STim.Szeto@Sun.COM 	if (!viewEntry->allTargets) {
5963*10691STim.Szeto@Sun.COM 		bcopy(viewEntry->targetGroup, iViewEntry.targetGroup,
5964*10691STim.Szeto@Sun.COM 		    sizeof (iViewEntry.targetGroup));
5965*10691STim.Szeto@Sun.COM 	} else {
5966*10691STim.Szeto@Sun.COM 		iViewEntry.allTargets = B_TRUE;
5967*10691STim.Szeto@Sun.COM 	}
5968*10691STim.Szeto@Sun.COM 
5969*10691STim.Szeto@Sun.COM 	if (viewEntry->luNbrValid) {
5970*10691STim.Szeto@Sun.COM 		iViewEntry.luNbrValid = B_TRUE;
5971*10691STim.Szeto@Sun.COM 		bcopy(viewEntry->luNbr, iViewEntry.luNbr,
5972*10691STim.Szeto@Sun.COM 		    sizeof (iViewEntry.luNbr));
5973*10691STim.Szeto@Sun.COM 	}
5974*10691STim.Szeto@Sun.COM 
5975*10691STim.Szeto@Sun.COM 	/*
5976*10691STim.Szeto@Sun.COM 	 * set users return view entry index valid flag to false
5977*10691STim.Szeto@Sun.COM 	 * in case of failure
5978*10691STim.Szeto@Sun.COM 	 */
5979*10691STim.Szeto@Sun.COM 	viewEntry->veIndexValid = B_FALSE;
5980*10691STim.Szeto@Sun.COM 
5981*10691STim.Szeto@Sun.COM 	/* Check to ensure service exists */
5982*10691STim.Szeto@Sun.COM 	if (psCheckService() != STMF_STATUS_SUCCESS) {
5983*10691STim.Szeto@Sun.COM 		return (STMF_ERROR_SERVICE_NOT_FOUND);
5984*10691STim.Szeto@Sun.COM 	}
5985*10691STim.Szeto@Sun.COM 
5986*10691STim.Szeto@Sun.COM 	/* call init */
5987*10691STim.Szeto@Sun.COM 	ret = initializeConfig();
5988*10691STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
5989*10691STim.Szeto@Sun.COM 		return (ret);
5990*10691STim.Szeto@Sun.COM 	}
5991*10691STim.Szeto@Sun.COM 
5992*10691STim.Szeto@Sun.COM 	/*
5993*10691STim.Szeto@Sun.COM 	 * Open control node for stmf
5994*10691STim.Szeto@Sun.COM 	 */
5995*10691STim.Szeto@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
5996*10691STim.Szeto@Sun.COM 		return (ret);
5997*10691STim.Szeto@Sun.COM 
5998*10691STim.Szeto@Sun.COM 	/*
5999*10691STim.Szeto@Sun.COM 	 * Validate lun# in the view entry from the driver
6000*10691STim.Szeto@Sun.COM 	 */
6001*10691STim.Szeto@Sun.COM 	ret = validateLunNumIoctl(fd, &iViewEntry);
6002*10691STim.Szeto@Sun.COM 	(void) close(fd);
6003*10691STim.Szeto@Sun.COM 
6004*10691STim.Szeto@Sun.COM 	/* save available lun number */
6005*10691STim.Szeto@Sun.COM 	if (!viewEntry->luNbrValid) {
6006*10691STim.Szeto@Sun.COM 		bcopy(iViewEntry.luNbr, viewEntry->luNbr,
6007*10691STim.Szeto@Sun.COM 		    sizeof (iViewEntry.luNbr));
6008*10691STim.Szeto@Sun.COM 	}
6009*10691STim.Szeto@Sun.COM 
6010*10691STim.Szeto@Sun.COM 	return (ret);
6011*10691STim.Szeto@Sun.COM }
6012