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:
345*9884STim.Szeto@Sun.COM 				switch (stmfIoctl.stmf_error) {
346*9884STim.Szeto@Sun.COM 					case STMF_IOCERR_TG_NEED_TG_OFFLINE:
347*9884STim.Szeto@Sun.COM 						ret = STMF_ERROR_TG_ONLINE;
348*9884STim.Szeto@Sun.COM 						break;
349*9884STim.Szeto@Sun.COM 					default:
350*9884STim.Szeto@Sun.COM 						ret = STMF_ERROR_BUSY;
351*9884STim.Szeto@Sun.COM 						break;
352*9884STim.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;
10819585STim.Szeto@Sun.COM 	int sluBufSize = 0;
10829585STim.Szeto@Sun.COM 	int bufOffset = 0;
10839585STim.Szeto@Sun.COM 	int fd = 0;
10849585STim.Szeto@Sun.COM 	int ioctlRet;
10859585STim.Szeto@Sun.COM 	int savedErrno;
10869585STim.Szeto@Sun.COM 	stmfGuid guid;
10879585STim.Szeto@Sun.COM 	stmf_iocdata_t sbdIoctl = {0};
10889585STim.Szeto@Sun.COM 
10899585STim.Szeto@Sun.COM 	sbd_create_and_reg_lu_t *sbdLu = NULL;
10909585STim.Szeto@Sun.COM 
10919585STim.Szeto@Sun.COM 	/*
10929585STim.Szeto@Sun.COM 	 * Open control node for sbd
10939585STim.Szeto@Sun.COM 	 */
10949585STim.Szeto@Sun.COM 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
10959585STim.Szeto@Sun.COM 		return (ret);
10969585STim.Szeto@Sun.COM 
10979585STim.Szeto@Sun.COM 	/* data file name must be specified */
10989585STim.Szeto@Sun.COM 	if (disk->luDataFileNameValid) {
10999585STim.Szeto@Sun.COM 		dataFileNameLen = strlen(disk->luDataFileName);
11009585STim.Szeto@Sun.COM 	} else {
11019585STim.Szeto@Sun.COM 		(void) close(fd);
11029585STim.Szeto@Sun.COM 		return (STMF_ERROR_MISSING_PROP_VAL);
11039585STim.Szeto@Sun.COM 	}
11049585STim.Szeto@Sun.COM 
11059585STim.Szeto@Sun.COM 	sluBufSize += dataFileNameLen + 1;
11069585STim.Szeto@Sun.COM 
11079585STim.Szeto@Sun.COM 	if (disk->luMetaFileNameValid) {
11089585STim.Szeto@Sun.COM 		metaFileNameLen = strlen(disk->luMetaFileName);
11099585STim.Szeto@Sun.COM 		sluBufSize += metaFileNameLen + 1;
11109585STim.Szeto@Sun.COM 	}
11119585STim.Szeto@Sun.COM 
11129585STim.Szeto@Sun.COM 	serialNumLen = strlen(disk->serialNum);
11139585STim.Szeto@Sun.COM 	sluBufSize += serialNumLen;
11149585STim.Szeto@Sun.COM 
11159585STim.Szeto@Sun.COM 	if (disk->luAliasValid) {
11169585STim.Szeto@Sun.COM 		luAliasLen = strlen(disk->luAlias);
11179585STim.Szeto@Sun.COM 		sluBufSize += luAliasLen + 1;
11189585STim.Szeto@Sun.COM 	}
11199585STim.Szeto@Sun.COM 
11209585STim.Szeto@Sun.COM 	/*
11219585STim.Szeto@Sun.COM 	 * 8 is the size of the buffer set aside for
11229585STim.Szeto@Sun.COM 	 * concatenation of variable length fields
11239585STim.Szeto@Sun.COM 	 */
11249585STim.Szeto@Sun.COM 	sbdLu = (sbd_create_and_reg_lu_t *)calloc(1,
11259585STim.Szeto@Sun.COM 	    sizeof (sbd_create_and_reg_lu_t) + sluBufSize - 8);
11269585STim.Szeto@Sun.COM 	if (sbdLu == NULL) {
11279585STim.Szeto@Sun.COM 		return (STMF_ERROR_NOMEM);
11289585STim.Szeto@Sun.COM 	}
11299585STim.Szeto@Sun.COM 
11309585STim.Szeto@Sun.COM 	sbdLu->slu_struct_size = sizeof (sbd_create_and_reg_lu_t) +
11319585STim.Szeto@Sun.COM 	    sluBufSize - 8;
11329585STim.Szeto@Sun.COM 
11339585STim.Szeto@Sun.COM 	if (metaFileNameLen) {
11349585STim.Szeto@Sun.COM 		sbdLu->slu_meta_fname_valid = 1;
11359585STim.Szeto@Sun.COM 		sbdLu->slu_meta_fname_off = bufOffset;
11369585STim.Szeto@Sun.COM 		bcopy(disk->luMetaFileName, &(sbdLu->slu_buf[bufOffset]),
11379585STim.Szeto@Sun.COM 		    metaFileNameLen + 1);
11389585STim.Szeto@Sun.COM 		bufOffset += metaFileNameLen + 1;
11399585STim.Szeto@Sun.COM 	}
11409585STim.Szeto@Sun.COM 
11419585STim.Szeto@Sun.COM 	bcopy(disk->luDataFileName, &(sbdLu->slu_buf[bufOffset]),
11429585STim.Szeto@Sun.COM 	    dataFileNameLen + 1);
11439585STim.Szeto@Sun.COM 	sbdLu->slu_data_fname_off = bufOffset;
11449585STim.Szeto@Sun.COM 	bufOffset += dataFileNameLen + 1;
11459585STim.Szeto@Sun.COM 
11469585STim.Szeto@Sun.COM 	/* currently, serial # is not passed null terminated to the driver */
11479585STim.Szeto@Sun.COM 	if (disk->serialNumValid) {
11489585STim.Szeto@Sun.COM 		sbdLu->slu_serial_valid = 1;
11499585STim.Szeto@Sun.COM 		sbdLu->slu_serial_off = bufOffset;
11509585STim.Szeto@Sun.COM 		sbdLu->slu_serial_size = serialNumLen;
11519585STim.Szeto@Sun.COM 		bcopy(disk->serialNum, &(sbdLu->slu_buf[bufOffset]),
11529585STim.Szeto@Sun.COM 		    serialNumLen);
11539585STim.Szeto@Sun.COM 		bufOffset += serialNumLen;
11549585STim.Szeto@Sun.COM 	}
11559585STim.Szeto@Sun.COM 
11569585STim.Szeto@Sun.COM 	if (disk->luAliasValid) {
11579585STim.Szeto@Sun.COM 		sbdLu->slu_alias_valid = 1;
11589585STim.Szeto@Sun.COM 		sbdLu->slu_alias_off = bufOffset;
11599585STim.Szeto@Sun.COM 		bcopy(disk->luAlias, &(sbdLu->slu_buf[bufOffset]),
11609585STim.Szeto@Sun.COM 		    luAliasLen + 1);
11619585STim.Szeto@Sun.COM 		bufOffset += luAliasLen + 1;
11629585STim.Szeto@Sun.COM 	}
11639585STim.Szeto@Sun.COM 
11649585STim.Szeto@Sun.COM 	if (disk->luSizeValid) {
11659585STim.Szeto@Sun.COM 		sbdLu->slu_lu_size_valid = 1;
11669585STim.Szeto@Sun.COM 		sbdLu->slu_lu_size = disk->luSize;
11679585STim.Szeto@Sun.COM 	}
11689585STim.Szeto@Sun.COM 
11699585STim.Szeto@Sun.COM 	if (disk->luGuidValid) {
11709585STim.Szeto@Sun.COM 		sbdLu->slu_guid_valid = 1;
11719585STim.Szeto@Sun.COM 		bcopy(disk->luGuid, sbdLu->slu_guid, sizeof (disk->luGuid));
11729585STim.Szeto@Sun.COM 	}
11739585STim.Szeto@Sun.COM 
11749585STim.Szeto@Sun.COM 	if (disk->vidValid) {
11759585STim.Szeto@Sun.COM 		sbdLu->slu_vid_valid = 1;
11769585STim.Szeto@Sun.COM 		bcopy(disk->vid, sbdLu->slu_vid, sizeof (disk->vid));
11779585STim.Szeto@Sun.COM 	}
11789585STim.Szeto@Sun.COM 
11799585STim.Szeto@Sun.COM 	if (disk->pidValid) {
11809585STim.Szeto@Sun.COM 		sbdLu->slu_pid_valid = 1;
11819585STim.Szeto@Sun.COM 		bcopy(disk->pid, sbdLu->slu_pid, sizeof (disk->pid));
11829585STim.Szeto@Sun.COM 	}
11839585STim.Szeto@Sun.COM 
11849585STim.Szeto@Sun.COM 	if (disk->revValid) {
11859585STim.Szeto@Sun.COM 		sbdLu->slu_rev_valid = 1;
11869585STim.Szeto@Sun.COM 		bcopy(disk->rev, sbdLu->slu_rev, sizeof (disk->rev));
11879585STim.Szeto@Sun.COM 	}
11889585STim.Szeto@Sun.COM 
11899585STim.Szeto@Sun.COM 	if (disk->companyIdValid) {
11909585STim.Szeto@Sun.COM 		sbdLu->slu_company_id_valid = 1;
11919585STim.Szeto@Sun.COM 		sbdLu->slu_company_id = disk->companyId;
11929585STim.Szeto@Sun.COM 	}
11939585STim.Szeto@Sun.COM 
11949585STim.Szeto@Sun.COM 	if (disk->blkSizeValid) {
11959585STim.Szeto@Sun.COM 		sbdLu->slu_blksize_valid = 1;
11969585STim.Szeto@Sun.COM 		sbdLu->slu_blksize = disk->blkSize;
11979585STim.Szeto@Sun.COM 	}
11989585STim.Szeto@Sun.COM 
11999585STim.Szeto@Sun.COM 	if (disk->writeProtectEnableValid) {
12009585STim.Szeto@Sun.COM 		if (disk->writeProtectEnable) {
12019585STim.Szeto@Sun.COM 			sbdLu->slu_write_protected = 1;
12029585STim.Szeto@Sun.COM 		}
12039585STim.Szeto@Sun.COM 	}
12049585STim.Szeto@Sun.COM 
12059585STim.Szeto@Sun.COM 	if (disk->writebackCacheDisableValid) {
12069585STim.Szeto@Sun.COM 		sbdLu->slu_writeback_cache_disable_valid = 1;
12079585STim.Szeto@Sun.COM 		if (disk->writebackCacheDisable) {
12089585STim.Szeto@Sun.COM 			sbdLu->slu_writeback_cache_disable = 1;
12099585STim.Szeto@Sun.COM 		}
12109585STim.Szeto@Sun.COM 	}
12119585STim.Szeto@Sun.COM 
12129585STim.Szeto@Sun.COM 	sbdIoctl.stmf_version = STMF_VERSION_1;
12139585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf_size = sbdLu->slu_struct_size;
12149585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdLu;
12159585STim.Szeto@Sun.COM 	sbdIoctl.stmf_obuf_size = sbdLu->slu_struct_size;
12169585STim.Szeto@Sun.COM 	sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdLu;
12179585STim.Szeto@Sun.COM 
12189585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, SBD_IOCTL_CREATE_AND_REGISTER_LU, &sbdIoctl);
12199585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
12209585STim.Szeto@Sun.COM 		savedErrno = errno;
12219585STim.Szeto@Sun.COM 		switch (savedErrno) {
12229585STim.Szeto@Sun.COM 			case EBUSY:
12239585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
12249585STim.Szeto@Sun.COM 				break;
12259585STim.Szeto@Sun.COM 			case EPERM:
12269585STim.Szeto@Sun.COM 			case EACCES:
12279585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
12289585STim.Szeto@Sun.COM 				break;
12299585STim.Szeto@Sun.COM 			default:
12309585STim.Szeto@Sun.COM 				diskError(sbdIoctl.stmf_error, &ret);
12319585STim.Szeto@Sun.COM 				if (ret == STMF_STATUS_ERROR) {
12329585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
12339585STim.Szeto@Sun.COM 					"createDiskLu:ioctl "
12349585STim.Szeto@Sun.COM 					"error(%d) (%d) (%d)", ioctlRet,
12359585STim.Szeto@Sun.COM 					    sbdIoctl.stmf_error, savedErrno);
12369585STim.Szeto@Sun.COM 				}
12379585STim.Szeto@Sun.COM 				break;
12389585STim.Szeto@Sun.COM 		}
12399585STim.Szeto@Sun.COM 	}
12409585STim.Szeto@Sun.COM 
12419585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
12429585STim.Szeto@Sun.COM 		goto done;
12439585STim.Szeto@Sun.COM 	}
12449585STim.Szeto@Sun.COM 
12459585STim.Szeto@Sun.COM 	/*
12469585STim.Szeto@Sun.COM 	 * on success, copy the resulting guid into the caller's guid if not
12479585STim.Szeto@Sun.COM 	 * NULL
12489585STim.Szeto@Sun.COM 	 */
12499585STim.Szeto@Sun.COM 	if (createdGuid) {
12509585STim.Szeto@Sun.COM 		bcopy(sbdLu->slu_guid, createdGuid->guid,
12519585STim.Szeto@Sun.COM 		    sizeof (sbdLu->slu_guid));
12529585STim.Szeto@Sun.COM 	}
12539585STim.Szeto@Sun.COM 
12549585STim.Szeto@Sun.COM 	bcopy(sbdLu->slu_guid, guid.guid, sizeof (sbdLu->slu_guid));
12559585STim.Szeto@Sun.COM 	if (disk->luMetaFileNameValid) {
12569585STim.Szeto@Sun.COM 		ret = addGuidToDiskStore(&guid, disk->luMetaFileName);
12579585STim.Szeto@Sun.COM 	} else {
12589585STim.Szeto@Sun.COM 		ret = addGuidToDiskStore(&guid, disk->luDataFileName);
12599585STim.Szeto@Sun.COM 	}
12609585STim.Szeto@Sun.COM done:
12619585STim.Szeto@Sun.COM 	free(sbdLu);
12629585STim.Szeto@Sun.COM 	(void) close(fd);
12639585STim.Szeto@Sun.COM 	return (ret);
12649585STim.Szeto@Sun.COM }
12659585STim.Szeto@Sun.COM 
12669585STim.Szeto@Sun.COM 
12679585STim.Szeto@Sun.COM /*
12689585STim.Szeto@Sun.COM  * stmfImportLu
12699585STim.Szeto@Sun.COM  *
12709585STim.Szeto@Sun.COM  * Purpose: Import a previously created logical unit
12719585STim.Szeto@Sun.COM  *
12729585STim.Szeto@Sun.COM  * dType - Type of logical unit
12739585STim.Szeto@Sun.COM  *         Can be: STMF_DISK
12749585STim.Szeto@Sun.COM  *
12759585STim.Szeto@Sun.COM  * luGuid - If non-NULL, on success, contains the guid of the imported logical
12769585STim.Szeto@Sun.COM  *	    unit
12779585STim.Szeto@Sun.COM  *
12789585STim.Szeto@Sun.COM  * fname - A file name where the metadata resides
12799585STim.Szeto@Sun.COM  *
12809585STim.Szeto@Sun.COM  */
12819585STim.Szeto@Sun.COM int
12829585STim.Szeto@Sun.COM stmfImportLu(uint16_t dType, char *fname, stmfGuid *luGuid)
12839585STim.Szeto@Sun.COM {
12849585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
12859585STim.Szeto@Sun.COM 
12869585STim.Szeto@Sun.COM 	if (dType == STMF_DISK) {
12879585STim.Szeto@Sun.COM 		ret = importDiskLu(fname, luGuid);
12889585STim.Szeto@Sun.COM 	} else {
12899585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
12909585STim.Szeto@Sun.COM 	}
12919585STim.Szeto@Sun.COM 
12929585STim.Szeto@Sun.COM 	return (ret);
12939585STim.Szeto@Sun.COM }
12949585STim.Szeto@Sun.COM 
12959585STim.Szeto@Sun.COM /*
12969585STim.Szeto@Sun.COM  * importDiskLu
12979585STim.Szeto@Sun.COM  *
12989585STim.Szeto@Sun.COM  * filename - filename to import
12999585STim.Szeto@Sun.COM  * createdGuid - if not NULL, on success contains the imported guid
13009585STim.Szeto@Sun.COM  *
13019585STim.Szeto@Sun.COM  */
13029585STim.Szeto@Sun.COM static int
13039585STim.Szeto@Sun.COM importDiskLu(char *fname, stmfGuid *createdGuid)
13049585STim.Szeto@Sun.COM {
13059585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
13069585STim.Szeto@Sun.COM 	int fd = 0;
13079585STim.Szeto@Sun.COM 	int ioctlRet;
13089585STim.Szeto@Sun.COM 	int savedErrno;
13099585STim.Szeto@Sun.COM 	int metaFileNameLen;
13109585STim.Szeto@Sun.COM 	stmfGuid iGuid;
13119585STim.Szeto@Sun.COM 	int iluBufSize = 0;
13129585STim.Szeto@Sun.COM 	sbd_import_lu_t *sbdLu = NULL;
13139585STim.Szeto@Sun.COM 	stmf_iocdata_t sbdIoctl = {0};
13149585STim.Szeto@Sun.COM 
13159585STim.Szeto@Sun.COM 	if (fname == NULL) {
13169585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
13179585STim.Szeto@Sun.COM 	}
13189585STim.Szeto@Sun.COM 
13199585STim.Szeto@Sun.COM 	/*
13209585STim.Szeto@Sun.COM 	 * Open control node for sbd
13219585STim.Szeto@Sun.COM 	 */
13229585STim.Szeto@Sun.COM 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
13239585STim.Szeto@Sun.COM 		return (ret);
13249585STim.Szeto@Sun.COM 
13259585STim.Szeto@Sun.COM 	metaFileNameLen = strlen(fname);
13269585STim.Szeto@Sun.COM 	iluBufSize += metaFileNameLen + 1;
13279585STim.Szeto@Sun.COM 
13289585STim.Szeto@Sun.COM 	/*
13299585STim.Szeto@Sun.COM 	 * 8 is the size of the buffer set aside for
13309585STim.Szeto@Sun.COM 	 * concatenation of variable length fields
13319585STim.Szeto@Sun.COM 	 */
13329585STim.Szeto@Sun.COM 	sbdLu = (sbd_import_lu_t *)calloc(1,
13339585STim.Szeto@Sun.COM 	    sizeof (sbd_import_lu_t) + iluBufSize - 8);
13349585STim.Szeto@Sun.COM 	if (sbdLu == NULL) {
13359585STim.Szeto@Sun.COM 		(void) close(fd);
13369585STim.Szeto@Sun.COM 		return (STMF_ERROR_NOMEM);
13379585STim.Szeto@Sun.COM 	}
13389585STim.Szeto@Sun.COM 
13399585STim.Szeto@Sun.COM 	/*
13409585STim.Szeto@Sun.COM 	 * Accept either a data file or meta data file.
13419585STim.Szeto@Sun.COM 	 * sbd will do the right thing here either way.
13429585STim.Szeto@Sun.COM 	 * i.e. if it's a data file, it assumes that the
13439585STim.Szeto@Sun.COM 	 * meta data is shared with the data.
13449585STim.Szeto@Sun.COM 	 */
13459585STim.Szeto@Sun.COM 	(void) strncpy(sbdLu->ilu_meta_fname, fname, metaFileNameLen);
13469585STim.Szeto@Sun.COM 
13479585STim.Szeto@Sun.COM 	sbdLu->ilu_struct_size = sizeof (sbd_import_lu_t) + iluBufSize - 8;
13489585STim.Szeto@Sun.COM 
13499585STim.Szeto@Sun.COM 	sbdIoctl.stmf_version = STMF_VERSION_1;
13509585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf_size = sbdLu->ilu_struct_size;
13519585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdLu;
13529585STim.Szeto@Sun.COM 	sbdIoctl.stmf_obuf_size = sbdLu->ilu_struct_size;
13539585STim.Szeto@Sun.COM 	sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdLu;
13549585STim.Szeto@Sun.COM 
13559585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, SBD_IOCTL_IMPORT_LU, &sbdIoctl);
13569585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
13579585STim.Szeto@Sun.COM 		savedErrno = errno;
13589585STim.Szeto@Sun.COM 		switch (savedErrno) {
13599585STim.Szeto@Sun.COM 			case EBUSY:
13609585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
13619585STim.Szeto@Sun.COM 				break;
13629585STim.Szeto@Sun.COM 			case EPERM:
13639585STim.Szeto@Sun.COM 			case EACCES:
13649585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
13659585STim.Szeto@Sun.COM 				break;
13669585STim.Szeto@Sun.COM 			default:
13679585STim.Szeto@Sun.COM 				diskError(sbdIoctl.stmf_error, &ret);
13689585STim.Szeto@Sun.COM 				if (ret == STMF_STATUS_ERROR) {
13699585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
13709585STim.Szeto@Sun.COM 					"importDiskLu:ioctl "
13719585STim.Szeto@Sun.COM 					"error(%d) (%d) (%d)", ioctlRet,
13729585STim.Szeto@Sun.COM 					    sbdIoctl.stmf_error, savedErrno);
13739585STim.Szeto@Sun.COM 				}
13749585STim.Szeto@Sun.COM 				break;
13759585STim.Szeto@Sun.COM 		}
13769585STim.Szeto@Sun.COM 	}
13779585STim.Szeto@Sun.COM 
13789585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
13799585STim.Szeto@Sun.COM 		goto done;
13809585STim.Szeto@Sun.COM 	}
13819585STim.Szeto@Sun.COM 
13829585STim.Szeto@Sun.COM 	/*
13839585STim.Szeto@Sun.COM 	 * on success, copy the resulting guid into the caller's guid if not
13849585STim.Szeto@Sun.COM 	 * NULL and add it to the persistent store for sbd
13859585STim.Szeto@Sun.COM 	 */
13869585STim.Szeto@Sun.COM 	if (createdGuid) {
13879585STim.Szeto@Sun.COM 		bcopy(sbdLu->ilu_ret_guid, createdGuid->guid,
13889585STim.Szeto@Sun.COM 		    sizeof (sbdLu->ilu_ret_guid));
13899585STim.Szeto@Sun.COM 		ret = addGuidToDiskStore(createdGuid, fname);
13909585STim.Szeto@Sun.COM 	} else {
13919585STim.Szeto@Sun.COM 		bcopy(sbdLu->ilu_ret_guid, iGuid.guid,
13929585STim.Szeto@Sun.COM 		    sizeof (sbdLu->ilu_ret_guid));
13939585STim.Szeto@Sun.COM 		ret = addGuidToDiskStore(&iGuid, fname);
13949585STim.Szeto@Sun.COM 	}
13959585STim.Szeto@Sun.COM done:
13969585STim.Szeto@Sun.COM 	free(sbdLu);
13979585STim.Szeto@Sun.COM 	(void) close(fd);
13989585STim.Szeto@Sun.COM 	return (ret);
13999585STim.Szeto@Sun.COM }
14009585STim.Szeto@Sun.COM 
14019585STim.Szeto@Sun.COM /*
14029585STim.Szeto@Sun.COM  * diskError
14039585STim.Szeto@Sun.COM  *
14049585STim.Szeto@Sun.COM  * Purpose: Translate sbd driver error
14059585STim.Szeto@Sun.COM  */
14069585STim.Szeto@Sun.COM static void
14079585STim.Szeto@Sun.COM diskError(uint32_t stmfError, int *ret)
14089585STim.Szeto@Sun.COM {
14099585STim.Szeto@Sun.COM 	switch (stmfError) {
14109585STim.Szeto@Sun.COM 		case SBD_RET_META_CREATION_FAILED:
14119585STim.Szeto@Sun.COM 		case SBD_RET_ZFS_META_CREATE_FAILED:
14129585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_META_CREATION;
14139585STim.Szeto@Sun.COM 			break;
14149585STim.Szeto@Sun.COM 		case SBD_RET_INVALID_BLKSIZE:
14159585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_INVALID_BLKSIZE;
14169585STim.Szeto@Sun.COM 			break;
14179585STim.Szeto@Sun.COM 		case SBD_RET_FILE_ALREADY_REGISTERED:
14189585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_FILE_IN_USE;
14199585STim.Szeto@Sun.COM 			break;
14209585STim.Szeto@Sun.COM 		case SBD_RET_GUID_ALREADY_REGISTERED:
14219585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_GUID_IN_USE;
14229585STim.Szeto@Sun.COM 			break;
14239585STim.Szeto@Sun.COM 		case SBD_RET_META_PATH_NOT_ABSOLUTE:
14249585STim.Szeto@Sun.COM 		case SBD_RET_META_FILE_LOOKUP_FAILED:
14259585STim.Szeto@Sun.COM 		case SBD_RET_META_FILE_OPEN_FAILED:
14269585STim.Szeto@Sun.COM 		case SBD_RET_META_FILE_GETATTR_FAILED:
14279585STim.Szeto@Sun.COM 		case SBD_RET_NO_META:
14289585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_META_FILE_NAME;
14299585STim.Szeto@Sun.COM 			break;
14309585STim.Szeto@Sun.COM 		case SBD_RET_DATA_PATH_NOT_ABSOLUTE:
14319585STim.Szeto@Sun.COM 		case SBD_RET_DATA_FILE_LOOKUP_FAILED:
14329585STim.Szeto@Sun.COM 		case SBD_RET_DATA_FILE_OPEN_FAILED:
14339585STim.Szeto@Sun.COM 		case SBD_RET_DATA_FILE_GETATTR_FAILED:
14349585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_DATA_FILE_NAME;
14359585STim.Szeto@Sun.COM 			break;
14369585STim.Szeto@Sun.COM 		case SBD_RET_FILE_SIZE_ERROR:
14379585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_FILE_SIZE_INVALID;
14389585STim.Szeto@Sun.COM 			break;
14399585STim.Szeto@Sun.COM 		case SBD_RET_SIZE_OUT_OF_RANGE:
14409585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_SIZE_OUT_OF_RANGE;
14419585STim.Szeto@Sun.COM 			break;
14429585STim.Szeto@Sun.COM 		case SBD_RET_LU_BUSY:
14439585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_LU_BUSY;
14449585STim.Szeto@Sun.COM 			break;
14459585STim.Szeto@Sun.COM 		case SBD_RET_WRITE_CACHE_SET_FAILED:
14469585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_WRITE_CACHE_SET;
14479585STim.Szeto@Sun.COM 			break;
14489585STim.Szeto@Sun.COM 		default:
14499585STim.Szeto@Sun.COM 			*ret = STMF_STATUS_ERROR;
14509585STim.Szeto@Sun.COM 			break;
14519585STim.Szeto@Sun.COM 	}
14529585STim.Szeto@Sun.COM }
14539585STim.Szeto@Sun.COM 
14549585STim.Szeto@Sun.COM /*
14559585STim.Szeto@Sun.COM  * Creates a logical unit resource of type STMF_DISK.
14569585STim.Szeto@Sun.COM  *
14579585STim.Szeto@Sun.COM  * No defaults should be set here as all defaults are derived from the
14589585STim.Szeto@Sun.COM  * driver's default settings.
14599585STim.Szeto@Sun.COM  */
14609585STim.Szeto@Sun.COM static int
14619585STim.Szeto@Sun.COM createDiskResource(luResourceImpl *hdl)
14629585STim.Szeto@Sun.COM {
14639585STim.Szeto@Sun.COM 	hdl->type = STMF_DISK;
14649585STim.Szeto@Sun.COM 
14659585STim.Szeto@Sun.COM 	hdl->resource = calloc(1, sizeof (diskResource));
14669585STim.Szeto@Sun.COM 	if (hdl->resource == NULL) {
14679585STim.Szeto@Sun.COM 		return (STMF_ERROR_NOMEM);
14689585STim.Szeto@Sun.COM 	}
14699585STim.Szeto@Sun.COM 
14709585STim.Szeto@Sun.COM 	return (STMF_STATUS_SUCCESS);
14719585STim.Szeto@Sun.COM }
14729585STim.Szeto@Sun.COM 
14739585STim.Szeto@Sun.COM /*
14749585STim.Szeto@Sun.COM  * stmfDeleteLu
14759585STim.Szeto@Sun.COM  *
14769585STim.Szeto@Sun.COM  * Purpose: Delete a logical unit
14779585STim.Szeto@Sun.COM  *
14789585STim.Szeto@Sun.COM  * hdl - handle to logical unit resource created via stmfCreateLuResource
14799585STim.Szeto@Sun.COM  *
14809585STim.Szeto@Sun.COM  * luGuid - If non-NULL, on success, contains the guid of the created logical
14819585STim.Szeto@Sun.COM  *	    unit
14829585STim.Szeto@Sun.COM  */
14839585STim.Szeto@Sun.COM int
14849585STim.Szeto@Sun.COM stmfDeleteLu(stmfGuid *luGuid)
14859585STim.Szeto@Sun.COM {
14869585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
14879585STim.Szeto@Sun.COM 	stmfLogicalUnitProperties luProps;
14889585STim.Szeto@Sun.COM 
14899585STim.Szeto@Sun.COM 	if (luGuid == NULL) {
14909585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
14919585STim.Szeto@Sun.COM 	}
14929585STim.Szeto@Sun.COM 
14939585STim.Szeto@Sun.COM 	/* Check logical unit provider name to call correct dtype function */
14949585STim.Szeto@Sun.COM 	if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps))
14959585STim.Szeto@Sun.COM 	    != STMF_STATUS_SUCCESS) {
14969585STim.Szeto@Sun.COM 		return (ret);
14979585STim.Szeto@Sun.COM 	} else {
14989585STim.Szeto@Sun.COM 		if (strcmp(luProps.providerName, "sbd") == 0) {
14999585STim.Szeto@Sun.COM 			ret = deleteDiskLu(luGuid);
15009585STim.Szeto@Sun.COM 		} else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) {
15019585STim.Szeto@Sun.COM 			return (STMF_ERROR_NOT_FOUND);
15029585STim.Szeto@Sun.COM 		} else {
15039585STim.Szeto@Sun.COM 			return (STMF_ERROR_INVALID_ARG);
15049585STim.Szeto@Sun.COM 		}
15059585STim.Szeto@Sun.COM 	}
15069585STim.Szeto@Sun.COM 
15079585STim.Szeto@Sun.COM 	return (ret);
15089585STim.Szeto@Sun.COM }
15099585STim.Szeto@Sun.COM 
15109585STim.Szeto@Sun.COM static int
15119585STim.Szeto@Sun.COM deleteDiskLu(stmfGuid *luGuid)
15129585STim.Szeto@Sun.COM {
15139585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
15149585STim.Szeto@Sun.COM 	int fd;
15159585STim.Szeto@Sun.COM 	int savedErrno;
15169585STim.Szeto@Sun.COM 	int ioctlRet;
15179585STim.Szeto@Sun.COM 	sbd_delete_lu_t deleteLu = {0};
15189585STim.Szeto@Sun.COM 
15199585STim.Szeto@Sun.COM 	stmf_iocdata_t sbdIoctl = {0};
15209585STim.Szeto@Sun.COM 
15219585STim.Szeto@Sun.COM 	/*
15229585STim.Szeto@Sun.COM 	 * Open control node for sbd
15239585STim.Szeto@Sun.COM 	 */
15249585STim.Szeto@Sun.COM 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
15259585STim.Szeto@Sun.COM 		return (ret);
15269585STim.Szeto@Sun.COM 
15279585STim.Szeto@Sun.COM 	ret = removeGuidFromDiskStore(luGuid);
15289585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
15299585STim.Szeto@Sun.COM 		goto done;
15309585STim.Szeto@Sun.COM 	}
15319585STim.Szeto@Sun.COM 
15329585STim.Szeto@Sun.COM 	bcopy(luGuid, deleteLu.dlu_guid, sizeof (deleteLu.dlu_guid));
15339585STim.Szeto@Sun.COM 	deleteLu.dlu_by_guid = 1;
15349585STim.Szeto@Sun.COM 
15359585STim.Szeto@Sun.COM 	sbdIoctl.stmf_version = STMF_VERSION_1;
15369585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf_size = sizeof (deleteLu);
15379585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)&deleteLu;
15389585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, SBD_IOCTL_DELETE_LU, &sbdIoctl);
15399585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
15409585STim.Szeto@Sun.COM 		savedErrno = errno;
15419585STim.Szeto@Sun.COM 		switch (savedErrno) {
15429585STim.Szeto@Sun.COM 			case EBUSY:
15439585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
15449585STim.Szeto@Sun.COM 				break;
15459585STim.Szeto@Sun.COM 			case EPERM:
15469585STim.Szeto@Sun.COM 			case EACCES:
15479585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
15489585STim.Szeto@Sun.COM 				break;
15499585STim.Szeto@Sun.COM 			case ENOENT:
15509585STim.Szeto@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
15519585STim.Szeto@Sun.COM 				break;
15529585STim.Szeto@Sun.COM 			default:
15539585STim.Szeto@Sun.COM 				syslog(LOG_DEBUG,
15549585STim.Szeto@Sun.COM 				    "deleteDiskLu:ioctl error(%d) (%d) (%d)",
15559585STim.Szeto@Sun.COM 				    ioctlRet, sbdIoctl.stmf_error, savedErrno);
15569585STim.Szeto@Sun.COM 				ret = STMF_STATUS_ERROR;
15579585STim.Szeto@Sun.COM 				break;
15589585STim.Szeto@Sun.COM 		}
15599585STim.Szeto@Sun.COM 	}
15609585STim.Szeto@Sun.COM 
15619585STim.Szeto@Sun.COM done:
15629585STim.Szeto@Sun.COM 	(void) close(fd);
15639585STim.Szeto@Sun.COM 	return (ret);
15649585STim.Szeto@Sun.COM }
15659585STim.Szeto@Sun.COM 
15669585STim.Szeto@Sun.COM /*
15679585STim.Szeto@Sun.COM  * stmfModifyLu
15689585STim.Szeto@Sun.COM  *
15699585STim.Szeto@Sun.COM  * Purpose: Modify properties of a logical unit
15709585STim.Szeto@Sun.COM  *
15719585STim.Szeto@Sun.COM  * luGuid - guid of registered logical unit
15729585STim.Szeto@Sun.COM  * prop - property to modify
15739585STim.Szeto@Sun.COM  * propVal - property value to set
15749585STim.Szeto@Sun.COM  *
15759585STim.Szeto@Sun.COM  */
15769585STim.Szeto@Sun.COM int
15779585STim.Szeto@Sun.COM stmfModifyLu(stmfGuid *luGuid, uint32_t prop, const char *propVal)
15789585STim.Szeto@Sun.COM {
15799585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
15809585STim.Szeto@Sun.COM 	stmfLogicalUnitProperties luProps;
15819585STim.Szeto@Sun.COM 
15829585STim.Szeto@Sun.COM 	if (luGuid == NULL) {
15839585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
15849585STim.Szeto@Sun.COM 	}
15859585STim.Szeto@Sun.COM 
15869585STim.Szeto@Sun.COM 	/* Check logical unit provider name to call correct dtype function */
15879585STim.Szeto@Sun.COM 	if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps))
15889585STim.Szeto@Sun.COM 	    != STMF_STATUS_SUCCESS) {
15899585STim.Szeto@Sun.COM 		return (ret);
15909585STim.Szeto@Sun.COM 	} else {
15919585STim.Szeto@Sun.COM 		if (strcmp(luProps.providerName, "sbd") == 0) {
15929585STim.Szeto@Sun.COM 			ret = modifyDiskLuProp(luGuid, NULL, prop, propVal);
15939585STim.Szeto@Sun.COM 		} else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) {
15949585STim.Szeto@Sun.COM 			return (STMF_ERROR_NOT_FOUND);
15959585STim.Szeto@Sun.COM 		} else {
15969585STim.Szeto@Sun.COM 			return (STMF_ERROR_INVALID_ARG);
15979585STim.Szeto@Sun.COM 		}
15989585STim.Szeto@Sun.COM 	}
15999585STim.Szeto@Sun.COM 
16009585STim.Szeto@Sun.COM 	return (ret);
16019585STim.Szeto@Sun.COM }
16029585STim.Szeto@Sun.COM 
16039585STim.Szeto@Sun.COM /*
16049585STim.Szeto@Sun.COM  * stmfModifyLuByFname
16059585STim.Szeto@Sun.COM  *
16069585STim.Szeto@Sun.COM  * Purpose: Modify a device by filename. Device does not need to be registered.
16079585STim.Szeto@Sun.COM  *
16089585STim.Szeto@Sun.COM  * dType - type of device to modify
16099585STim.Szeto@Sun.COM  *         STMF_DISK
16109585STim.Szeto@Sun.COM  *
16119585STim.Szeto@Sun.COM  * fname - filename or meta filename
16129585STim.Szeto@Sun.COM  * prop - valid property identifier
16139585STim.Szeto@Sun.COM  * propVal - property value
16149585STim.Szeto@Sun.COM  *
16159585STim.Szeto@Sun.COM  */
16169585STim.Szeto@Sun.COM int
16179585STim.Szeto@Sun.COM stmfModifyLuByFname(uint16_t dType, const char *fname, uint32_t prop,
16189585STim.Szeto@Sun.COM     const char *propVal)
16199585STim.Szeto@Sun.COM {
16209585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
16219585STim.Szeto@Sun.COM 	if (fname == NULL) {
16229585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
16239585STim.Szeto@Sun.COM 	}
16249585STim.Szeto@Sun.COM 
16259585STim.Szeto@Sun.COM 	if (dType == STMF_DISK) {
16269585STim.Szeto@Sun.COM 		ret = modifyDiskLuProp(NULL, fname, prop, propVal);
16279585STim.Szeto@Sun.COM 	} else {
16289585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
16299585STim.Szeto@Sun.COM 	}
16309585STim.Szeto@Sun.COM 
16319585STim.Szeto@Sun.COM 	return (ret);
16329585STim.Szeto@Sun.COM }
16339585STim.Szeto@Sun.COM 
16349585STim.Szeto@Sun.COM static int
16359585STim.Szeto@Sun.COM modifyDiskLuProp(stmfGuid *luGuid, const char *fname, uint32_t prop,
16369585STim.Szeto@Sun.COM     const char *propVal)
16379585STim.Szeto@Sun.COM {
16389585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
16399585STim.Szeto@Sun.COM 	luResource hdl = NULL;
16409585STim.Szeto@Sun.COM 	luResourceImpl *luPropsHdl;
16419585STim.Szeto@Sun.COM 
16429585STim.Szeto@Sun.COM 	ret = stmfCreateLuResource(STMF_DISK, &hdl);
16439585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
16449585STim.Szeto@Sun.COM 		return (ret);
16459585STim.Szeto@Sun.COM 	}
16469585STim.Szeto@Sun.COM 	ret = validateModifyDiskProp(prop);
16479585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
16489585STim.Szeto@Sun.COM 		(void) stmfFreeLuResource(hdl);
16499585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_PROP);
16509585STim.Szeto@Sun.COM 	}
16519585STim.Szeto@Sun.COM 	ret = stmfSetLuProp(hdl, prop, propVal);
16529585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
16539585STim.Szeto@Sun.COM 		(void) stmfFreeLuResource(hdl);
16549585STim.Szeto@Sun.COM 		return (ret);
16559585STim.Szeto@Sun.COM 	}
16569585STim.Szeto@Sun.COM 	luPropsHdl = hdl;
16579585STim.Szeto@Sun.COM 	ret = modifyDiskLu((diskResource *)luPropsHdl->resource, luGuid, fname);
16589585STim.Szeto@Sun.COM 	(void) stmfFreeLuResource(hdl);
16599585STim.Szeto@Sun.COM 	return (ret);
16609585STim.Szeto@Sun.COM }
16619585STim.Szeto@Sun.COM 
16629585STim.Szeto@Sun.COM static int
16639585STim.Szeto@Sun.COM validateModifyDiskProp(uint32_t prop)
16649585STim.Szeto@Sun.COM {
16659585STim.Szeto@Sun.COM 	switch (prop) {
16669585STim.Szeto@Sun.COM 		case STMF_LU_PROP_ALIAS:
16679585STim.Szeto@Sun.COM 		case STMF_LU_PROP_SIZE:
16689585STim.Szeto@Sun.COM 		case STMF_LU_PROP_WRITE_PROTECT:
16699585STim.Szeto@Sun.COM 		case STMF_LU_PROP_WRITE_CACHE_DISABLE:
16709585STim.Szeto@Sun.COM 			return (STMF_STATUS_SUCCESS);
16719585STim.Szeto@Sun.COM 			break;
16729585STim.Szeto@Sun.COM 		default:
16739585STim.Szeto@Sun.COM 			return (STMF_STATUS_ERROR);
16749585STim.Szeto@Sun.COM 			break;
16759585STim.Szeto@Sun.COM 	}
16769585STim.Szeto@Sun.COM }
16779585STim.Szeto@Sun.COM 
16789585STim.Szeto@Sun.COM static int
16799585STim.Szeto@Sun.COM modifyDiskLu(diskResource *disk, stmfGuid *luGuid, const char *fname)
16809585STim.Szeto@Sun.COM {
16819585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
16829585STim.Szeto@Sun.COM 	int luAliasLen = 0;
16839585STim.Szeto@Sun.COM 	int mluBufSize = 0;
16849585STim.Szeto@Sun.COM 	int bufOffset = 0;
16859585STim.Szeto@Sun.COM 	int fd = 0;
16869585STim.Szeto@Sun.COM 	int ioctlRet;
16879585STim.Szeto@Sun.COM 	int savedErrno;
16889585STim.Szeto@Sun.COM 	int fnameSize = 0;
16899585STim.Szeto@Sun.COM 	stmf_iocdata_t sbdIoctl = {0};
16909585STim.Szeto@Sun.COM 
16919585STim.Szeto@Sun.COM 	sbd_modify_lu_t *sbdLu = NULL;
16929585STim.Szeto@Sun.COM 
16939585STim.Szeto@Sun.COM 	if (luGuid == NULL && fname == NULL) {
16949585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
16959585STim.Szeto@Sun.COM 	}
16969585STim.Szeto@Sun.COM 
16979585STim.Szeto@Sun.COM 	if (fname) {
16989585STim.Szeto@Sun.COM 		fnameSize = strlen(fname) + 1;
16999585STim.Szeto@Sun.COM 		mluBufSize += fnameSize;
17009585STim.Szeto@Sun.COM 	}
17019585STim.Szeto@Sun.COM 
17029585STim.Szeto@Sun.COM 	/*
17039585STim.Szeto@Sun.COM 	 * Open control node for sbd
17049585STim.Szeto@Sun.COM 	 */
17059585STim.Szeto@Sun.COM 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
17069585STim.Szeto@Sun.COM 		return (ret);
17079585STim.Szeto@Sun.COM 
17089585STim.Szeto@Sun.COM 	if (disk->luAliasValid) {
17099585STim.Szeto@Sun.COM 		luAliasLen = strlen(disk->luAlias);
17109585STim.Szeto@Sun.COM 		mluBufSize += luAliasLen + 1;
17119585STim.Szeto@Sun.COM 	}
17129585STim.Szeto@Sun.COM 
17139585STim.Szeto@Sun.COM 	/*
17149585STim.Szeto@Sun.COM 	 * 8 is the size of the buffer set aside for
17159585STim.Szeto@Sun.COM 	 * concatenation of variable length fields
17169585STim.Szeto@Sun.COM 	 */
17179585STim.Szeto@Sun.COM 	sbdLu = (sbd_modify_lu_t *)calloc(1,
17189585STim.Szeto@Sun.COM 	    sizeof (sbd_modify_lu_t) + mluBufSize - 8 + fnameSize);
17199585STim.Szeto@Sun.COM 	if (sbdLu == NULL) {
17209585STim.Szeto@Sun.COM 		(void) close(fd);
17219585STim.Szeto@Sun.COM 		return (STMF_ERROR_NOMEM);
17229585STim.Szeto@Sun.COM 	}
17239585STim.Szeto@Sun.COM 
17249585STim.Szeto@Sun.COM 	sbdLu->mlu_struct_size = sizeof (sbd_modify_lu_t) +
17259585STim.Szeto@Sun.COM 	    mluBufSize - 8 + fnameSize;
17269585STim.Szeto@Sun.COM 
17279585STim.Szeto@Sun.COM 	if (disk->luAliasValid) {
17289585STim.Szeto@Sun.COM 		sbdLu->mlu_alias_valid = 1;
17299585STim.Szeto@Sun.COM 		sbdLu->mlu_alias_off = bufOffset;
17309585STim.Szeto@Sun.COM 		bcopy(disk->luAlias, &(sbdLu->mlu_buf[bufOffset]),
17319585STim.Szeto@Sun.COM 		    luAliasLen + 1);
17329585STim.Szeto@Sun.COM 		bufOffset += luAliasLen + 1;
17339585STim.Szeto@Sun.COM 	}
17349585STim.Szeto@Sun.COM 
17359585STim.Szeto@Sun.COM 	if (disk->luSizeValid) {
17369585STim.Szeto@Sun.COM 		sbdLu->mlu_lu_size_valid = 1;
17379585STim.Szeto@Sun.COM 		sbdLu->mlu_lu_size = disk->luSize;
17389585STim.Szeto@Sun.COM 	}
17399585STim.Szeto@Sun.COM 
17409585STim.Szeto@Sun.COM 	if (disk->writeProtectEnableValid) {
17419585STim.Szeto@Sun.COM 		sbdLu->mlu_write_protected_valid = 1;
17429585STim.Szeto@Sun.COM 		if (disk->writeProtectEnable) {
17439585STim.Szeto@Sun.COM 			sbdLu->mlu_write_protected = 1;
17449585STim.Szeto@Sun.COM 		}
17459585STim.Szeto@Sun.COM 	}
17469585STim.Szeto@Sun.COM 
17479585STim.Szeto@Sun.COM 	if (disk->writebackCacheDisableValid) {
17489585STim.Szeto@Sun.COM 		sbdLu->mlu_writeback_cache_disable_valid = 1;
17499585STim.Szeto@Sun.COM 		if (disk->writebackCacheDisable) {
17509585STim.Szeto@Sun.COM 			sbdLu->mlu_writeback_cache_disable = 1;
17519585STim.Szeto@Sun.COM 		}
17529585STim.Szeto@Sun.COM 	}
17539585STim.Szeto@Sun.COM 
17549585STim.Szeto@Sun.COM 	if (luGuid) {
17559585STim.Szeto@Sun.COM 		bcopy(luGuid, sbdLu->mlu_input_guid, sizeof (stmfGuid));
17569585STim.Szeto@Sun.COM 		sbdLu->mlu_by_guid = 1;
17579585STim.Szeto@Sun.COM 	} else {
17589585STim.Szeto@Sun.COM 		sbdLu->mlu_fname_off = bufOffset;
17599585STim.Szeto@Sun.COM 		bcopy(fname, &(sbdLu->mlu_buf[bufOffset]), fnameSize + 1);
17609585STim.Szeto@Sun.COM 		sbdLu->mlu_by_fname = 1;
17619585STim.Szeto@Sun.COM 	}
17629585STim.Szeto@Sun.COM 
17639585STim.Szeto@Sun.COM 	sbdIoctl.stmf_version = STMF_VERSION_1;
17649585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf_size = sbdLu->mlu_struct_size;
17659585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdLu;
17669585STim.Szeto@Sun.COM 
17679585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, SBD_IOCTL_MODIFY_LU, &sbdIoctl);
17689585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
17699585STim.Szeto@Sun.COM 		savedErrno = errno;
17709585STim.Szeto@Sun.COM 		switch (savedErrno) {
17719585STim.Szeto@Sun.COM 			case EBUSY:
17729585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
17739585STim.Szeto@Sun.COM 				break;
17749585STim.Szeto@Sun.COM 			case EPERM:
17759585STim.Szeto@Sun.COM 			case EACCES:
17769585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
17779585STim.Szeto@Sun.COM 				break;
17789585STim.Szeto@Sun.COM 			default:
17799585STim.Szeto@Sun.COM 				diskError(sbdIoctl.stmf_error, &ret);
17809585STim.Szeto@Sun.COM 				if (ret == STMF_STATUS_ERROR) {
17819585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
17829585STim.Szeto@Sun.COM 					"modifyDiskLu:ioctl "
17839585STim.Szeto@Sun.COM 					"error(%d) (%d) (%d)", ioctlRet,
17849585STim.Szeto@Sun.COM 					    sbdIoctl.stmf_error, savedErrno);
17859585STim.Szeto@Sun.COM 				}
17869585STim.Szeto@Sun.COM 				break;
17879585STim.Szeto@Sun.COM 		}
17889585STim.Szeto@Sun.COM 	}
17899585STim.Szeto@Sun.COM 
17909585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
17919585STim.Szeto@Sun.COM 		goto done;
17929585STim.Szeto@Sun.COM 	}
17939585STim.Szeto@Sun.COM 
17949585STim.Szeto@Sun.COM done:
17959585STim.Szeto@Sun.COM 	free(sbdLu);
17969585STim.Szeto@Sun.COM 	(void) close(fd);
17979585STim.Szeto@Sun.COM 	return (ret);
17989585STim.Szeto@Sun.COM }
17999585STim.Szeto@Sun.COM 
18009585STim.Szeto@Sun.COM /*
18019585STim.Szeto@Sun.COM  * removeGuidFromDiskStore
18029585STim.Szeto@Sun.COM  *
18039585STim.Szeto@Sun.COM  * Purpose: delete a logical unit from the sbd provider data
18049585STim.Szeto@Sun.COM  */
18059585STim.Szeto@Sun.COM static int
18069585STim.Szeto@Sun.COM removeGuidFromDiskStore(stmfGuid *guid)
18079585STim.Szeto@Sun.COM {
18089585STim.Szeto@Sun.COM 	return (persistDiskGuid(guid, NULL, B_FALSE));
18099585STim.Szeto@Sun.COM }
18109585STim.Szeto@Sun.COM 
18119585STim.Szeto@Sun.COM 
18129585STim.Szeto@Sun.COM /*
18139585STim.Szeto@Sun.COM  * addGuidToDiskStore
18149585STim.Szeto@Sun.COM  *
18159585STim.Szeto@Sun.COM  * Purpose: add a logical unit to the sbd provider data
18169585STim.Szeto@Sun.COM  */
18179585STim.Szeto@Sun.COM static int
18189585STim.Szeto@Sun.COM addGuidToDiskStore(stmfGuid *guid, char *filename)
18199585STim.Szeto@Sun.COM {
18209585STim.Szeto@Sun.COM 	return (persistDiskGuid(guid, filename, B_TRUE));
18219585STim.Szeto@Sun.COM }
18229585STim.Szeto@Sun.COM 
18239585STim.Szeto@Sun.COM 
18249585STim.Szeto@Sun.COM /*
18259585STim.Szeto@Sun.COM  * persistDiskGuid
18269585STim.Szeto@Sun.COM  *
18279585STim.Szeto@Sun.COM  * Purpose: Persist or unpersist a guid for the sbd provider data
18289585STim.Szeto@Sun.COM  *
18299585STim.Szeto@Sun.COM  */
18309585STim.Szeto@Sun.COM static int
18319585STim.Szeto@Sun.COM persistDiskGuid(stmfGuid *guid, char *filename, boolean_t persist)
18329585STim.Szeto@Sun.COM {
18339585STim.Szeto@Sun.COM 	char	    guidAsciiBuf[LU_ASCII_GUID_SIZE + 1] = {0};
18349585STim.Szeto@Sun.COM 	nvlist_t    *nvl = NULL;
18359585STim.Szeto@Sun.COM 
18369585STim.Szeto@Sun.COM 	uint64_t    setToken;
18379585STim.Szeto@Sun.COM 	boolean_t   retryGetProviderData = B_FALSE;
18389585STim.Szeto@Sun.COM 	boolean_t   newData = B_FALSE;
18399585STim.Szeto@Sun.COM 	int	    ret = STMF_STATUS_SUCCESS;
18409585STim.Szeto@Sun.COM 	int	    retryCnt = 0;
18419585STim.Szeto@Sun.COM 	int	    stmfRet;
18429585STim.Szeto@Sun.COM 
18439585STim.Szeto@Sun.COM 	/* if we're persisting a guid, there must be a filename */
18449585STim.Szeto@Sun.COM 	if (persist && !filename) {
18459585STim.Szeto@Sun.COM 		return (1);
18469585STim.Szeto@Sun.COM 	}
18479585STim.Szeto@Sun.COM 
18489585STim.Szeto@Sun.COM 	/* guid is stored in lowercase ascii hex */
18499585STim.Szeto@Sun.COM 	(void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf),
18509585STim.Szeto@Sun.COM 	    "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
18519585STim.Szeto@Sun.COM 	    "%02x%02x%02x%02x%02x%02x",
18529585STim.Szeto@Sun.COM 	    guid->guid[0], guid->guid[1], guid->guid[2], guid->guid[3],
18539585STim.Szeto@Sun.COM 	    guid->guid[4], guid->guid[5], guid->guid[6], guid->guid[7],
18549585STim.Szeto@Sun.COM 	    guid->guid[8], guid->guid[9], guid->guid[10], guid->guid[11],
18559585STim.Szeto@Sun.COM 	    guid->guid[12], guid->guid[13], guid->guid[14], guid->guid[15]);
18569585STim.Szeto@Sun.COM 
18579585STim.Szeto@Sun.COM 
18589585STim.Szeto@Sun.COM 	do {
18599585STim.Szeto@Sun.COM 		retryGetProviderData = B_FALSE;
18609585STim.Szeto@Sun.COM 		stmfRet = stmfGetProviderDataProt("sbd", &nvl,
18619585STim.Szeto@Sun.COM 		    STMF_LU_PROVIDER_TYPE, &setToken);
18629585STim.Szeto@Sun.COM 		if (stmfRet != STMF_STATUS_SUCCESS) {
18639585STim.Szeto@Sun.COM 			if (persist && stmfRet == STMF_ERROR_NOT_FOUND) {
18649585STim.Szeto@Sun.COM 				ret = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0);
18659585STim.Szeto@Sun.COM 				if (ret != 0) {
18669585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
18679585STim.Szeto@Sun.COM 					    "unpersistGuid:nvlist_alloc(%d)",
18689585STim.Szeto@Sun.COM 					    ret);
18699585STim.Szeto@Sun.COM 					ret = STMF_STATUS_ERROR;
18709585STim.Szeto@Sun.COM 					goto done;
18719585STim.Szeto@Sun.COM 				}
18729585STim.Szeto@Sun.COM 				newData = B_TRUE;
18739585STim.Szeto@Sun.COM 			} else {
18749585STim.Szeto@Sun.COM 				ret = stmfRet;
18759585STim.Szeto@Sun.COM 				goto done;
18769585STim.Szeto@Sun.COM 			}
18779585STim.Szeto@Sun.COM 		}
18789585STim.Szeto@Sun.COM 		if (persist) {
18799585STim.Szeto@Sun.COM 			ret = nvlist_add_string(nvl, guidAsciiBuf, filename);
18809585STim.Szeto@Sun.COM 		} else {
18819585STim.Szeto@Sun.COM 			ret = nvlist_remove(nvl, guidAsciiBuf,
18829585STim.Szeto@Sun.COM 			    DATA_TYPE_STRING);
18839585STim.Szeto@Sun.COM 			if (ret == ENOENT) {
18849585STim.Szeto@Sun.COM 				ret = 0;
18859585STim.Szeto@Sun.COM 			}
18869585STim.Szeto@Sun.COM 		}
18879585STim.Szeto@Sun.COM 		if (ret == 0) {
18889585STim.Szeto@Sun.COM 			if (newData) {
18899585STim.Szeto@Sun.COM 				stmfRet = stmfSetProviderDataProt("sbd", nvl,
18909585STim.Szeto@Sun.COM 				    STMF_LU_PROVIDER_TYPE, NULL);
18919585STim.Szeto@Sun.COM 			} else {
18929585STim.Szeto@Sun.COM 				stmfRet = stmfSetProviderDataProt("sbd", nvl,
18939585STim.Szeto@Sun.COM 				    STMF_LU_PROVIDER_TYPE, &setToken);
18949585STim.Szeto@Sun.COM 			}
18959585STim.Szeto@Sun.COM 			if (stmfRet != STMF_STATUS_SUCCESS) {
18969585STim.Szeto@Sun.COM 				if (stmfRet == STMF_ERROR_BUSY) {
18979585STim.Szeto@Sun.COM 					/* get/set failed, try again */
18989585STim.Szeto@Sun.COM 					retryGetProviderData = B_TRUE;
18999585STim.Szeto@Sun.COM 					if (retryCnt++ > MAX_PROVIDER_RETRY) {
19009585STim.Szeto@Sun.COM 						ret = stmfRet;
19019585STim.Szeto@Sun.COM 						break;
19029585STim.Szeto@Sun.COM 					}
19039585STim.Szeto@Sun.COM 					continue;
19049585STim.Szeto@Sun.COM 				} else if (stmfRet ==
19059585STim.Szeto@Sun.COM 				    STMF_ERROR_PROV_DATA_STALE) {
19069585STim.Szeto@Sun.COM 					/* update failed, try again */
19079585STim.Szeto@Sun.COM 					nvlist_free(nvl);
19089585STim.Szeto@Sun.COM 					nvl = NULL;
19099585STim.Szeto@Sun.COM 					retryGetProviderData = B_TRUE;
19109585STim.Szeto@Sun.COM 					if (retryCnt++ > MAX_PROVIDER_RETRY) {
19119585STim.Szeto@Sun.COM 						ret = stmfRet;
19129585STim.Szeto@Sun.COM 						break;
19139585STim.Szeto@Sun.COM 					}
19149585STim.Szeto@Sun.COM 					continue;
19159585STim.Szeto@Sun.COM 				} else {
19169585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
19179585STim.Szeto@Sun.COM 					    "unpersistGuid:error(%x)", stmfRet);
19189585STim.Szeto@Sun.COM 					ret = stmfRet;
19199585STim.Szeto@Sun.COM 				}
19209585STim.Szeto@Sun.COM 				break;
19219585STim.Szeto@Sun.COM 			}
19229585STim.Szeto@Sun.COM 		} else {
19239585STim.Szeto@Sun.COM 			syslog(LOG_DEBUG,
19249585STim.Szeto@Sun.COM 			    "unpersistGuid:error nvlist_add/remove(%d)",
19259585STim.Szeto@Sun.COM 			    ret);
19269585STim.Szeto@Sun.COM 			ret = STMF_STATUS_ERROR;
19279585STim.Szeto@Sun.COM 		}
19289585STim.Szeto@Sun.COM 	} while (retryGetProviderData);
19299585STim.Szeto@Sun.COM 
19309585STim.Szeto@Sun.COM done:
19319585STim.Szeto@Sun.COM 	nvlist_free(nvl);
19329585STim.Szeto@Sun.COM 	return (ret);
19339585STim.Szeto@Sun.COM }
19349585STim.Szeto@Sun.COM 
19359585STim.Szeto@Sun.COM 
19369585STim.Szeto@Sun.COM /*
19379585STim.Szeto@Sun.COM  * stmfGetLuProp
19389585STim.Szeto@Sun.COM  *
19399585STim.Szeto@Sun.COM  * Purpose: Get current value for a resource property
19409585STim.Szeto@Sun.COM  *
19419585STim.Szeto@Sun.COM  * hdl - luResource from a previous call to stmfCreateLuResource
19429585STim.Szeto@Sun.COM  *
19439585STim.Szeto@Sun.COM  * resourceProp - a valid resource property type
19449585STim.Szeto@Sun.COM  *
19459585STim.Szeto@Sun.COM  * propVal - void pointer to a pointer of the value to be retrieved
19469585STim.Szeto@Sun.COM  */
19479585STim.Szeto@Sun.COM int
19489585STim.Szeto@Sun.COM stmfGetLuProp(luResource hdl, uint32_t prop, char *propVal, size_t *propLen)
19499585STim.Szeto@Sun.COM {
19509585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
19519585STim.Szeto@Sun.COM 	luResourceImpl *luPropsHdl = hdl;
19529585STim.Szeto@Sun.COM 	if (hdl == NULL || propLen == NULL || propVal == NULL) {
19539585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
19549585STim.Szeto@Sun.COM 	}
19559585STim.Szeto@Sun.COM 
19569585STim.Szeto@Sun.COM 	if (luPropsHdl->type == STMF_DISK) {
19579585STim.Szeto@Sun.COM 		ret = getDiskProp(luPropsHdl, prop, propVal, propLen);
19589585STim.Szeto@Sun.COM 	} else {
19599585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
19609585STim.Szeto@Sun.COM 	}
19619585STim.Szeto@Sun.COM 
19629585STim.Szeto@Sun.COM 	return (ret);
19639585STim.Szeto@Sun.COM }
19649585STim.Szeto@Sun.COM 
19659585STim.Szeto@Sun.COM /*
19669585STim.Szeto@Sun.COM  * stmfGetLuResource
19679585STim.Szeto@Sun.COM  *
19689585STim.Szeto@Sun.COM  * Purpose: Get a logical unit resource handle for a given logical unit.
19699585STim.Szeto@Sun.COM  *
19709585STim.Szeto@Sun.COM  * hdl - pointer to luResource
19719585STim.Szeto@Sun.COM  */
19729585STim.Szeto@Sun.COM int
19739585STim.Szeto@Sun.COM stmfGetLuResource(stmfGuid *luGuid, luResource *hdl)
19749585STim.Szeto@Sun.COM {
19759585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
19769585STim.Szeto@Sun.COM 	stmfLogicalUnitProperties luProps;
19779585STim.Szeto@Sun.COM 
19789585STim.Szeto@Sun.COM 
19799585STim.Szeto@Sun.COM 	/* Check logical unit provider name to call correct dtype function */
19809585STim.Szeto@Sun.COM 	if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps))
19819585STim.Szeto@Sun.COM 	    != STMF_STATUS_SUCCESS) {
19829585STim.Szeto@Sun.COM 		return (ret);
19839585STim.Szeto@Sun.COM 	} else {
19849585STim.Szeto@Sun.COM 		if (strcmp(luProps.providerName, "sbd") == 0) {
19859585STim.Szeto@Sun.COM 			ret = getDiskAllProps(luGuid, hdl);
19869585STim.Szeto@Sun.COM 		} else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) {
19879585STim.Szeto@Sun.COM 			return (STMF_ERROR_NOT_FOUND);
19889585STim.Szeto@Sun.COM 		} else {
19899585STim.Szeto@Sun.COM 			return (STMF_ERROR_INVALID_ARG);
19909585STim.Szeto@Sun.COM 		}
19919585STim.Szeto@Sun.COM 	}
19929585STim.Szeto@Sun.COM 
19939585STim.Szeto@Sun.COM 	return (ret);
19949585STim.Szeto@Sun.COM }
19959585STim.Szeto@Sun.COM 
19969585STim.Szeto@Sun.COM /*
19979585STim.Szeto@Sun.COM  * getDiskAllProps
19989585STim.Szeto@Sun.COM  *
19999585STim.Szeto@Sun.COM  * Purpose: load all disk properties from sbd driver
20009585STim.Szeto@Sun.COM  *
20019585STim.Szeto@Sun.COM  * luGuid - guid of disk device for which properties are to be retrieved
20029585STim.Szeto@Sun.COM  * hdl - allocated luResource into which properties are to be copied
20039585STim.Szeto@Sun.COM  *
20049585STim.Szeto@Sun.COM  */
20059585STim.Szeto@Sun.COM static int
20069585STim.Szeto@Sun.COM getDiskAllProps(stmfGuid *luGuid, luResource *hdl)
20079585STim.Szeto@Sun.COM {
20089585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
20099585STim.Szeto@Sun.COM 	int fd;
20109585STim.Szeto@Sun.COM 	sbd_lu_props_t *sbdProps;
20119585STim.Szeto@Sun.COM 	int ioctlRet;
20129585STim.Szeto@Sun.COM 	int savedErrno;
20139585STim.Szeto@Sun.COM 	int sbdPropsSize = sizeof (*sbdProps) + MAX_SBD_PROPS;
20149585STim.Szeto@Sun.COM 	stmf_iocdata_t sbdIoctl = {0};
20159585STim.Szeto@Sun.COM 
20169585STim.Szeto@Sun.COM 	/*
20179585STim.Szeto@Sun.COM 	 * Open control node for sbd
20189585STim.Szeto@Sun.COM 	 */
20199585STim.Szeto@Sun.COM 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
20209585STim.Szeto@Sun.COM 		return (ret);
20219585STim.Szeto@Sun.COM 
20229585STim.Szeto@Sun.COM 
20239585STim.Szeto@Sun.COM 	*hdl = calloc(1, sizeof (luResourceImpl));
20249585STim.Szeto@Sun.COM 	if (*hdl == NULL) {
20259585STim.Szeto@Sun.COM 		(void) close(fd);
20269585STim.Szeto@Sun.COM 		return (STMF_ERROR_NOMEM);
20279585STim.Szeto@Sun.COM 	}
20289585STim.Szeto@Sun.COM 
20299585STim.Szeto@Sun.COM 	sbdProps = calloc(1, sbdPropsSize);
20309585STim.Szeto@Sun.COM 	if (sbdProps == NULL) {
20319585STim.Szeto@Sun.COM 		free(*hdl);
20329585STim.Szeto@Sun.COM 		(void) close(fd);
20339585STim.Szeto@Sun.COM 		return (STMF_ERROR_NOMEM);
20349585STim.Szeto@Sun.COM 	}
20359585STim.Szeto@Sun.COM 
20369585STim.Szeto@Sun.COM 	ret = createDiskResource((luResourceImpl *)*hdl);
20379585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
20389585STim.Szeto@Sun.COM 		free(*hdl);
20399585STim.Szeto@Sun.COM 		(void) close(fd);
20409585STim.Szeto@Sun.COM 		return (ret);
20419585STim.Szeto@Sun.COM 	}
20429585STim.Szeto@Sun.COM 
20439585STim.Szeto@Sun.COM 	sbdProps->slp_input_guid = 1;
20449585STim.Szeto@Sun.COM 	bcopy(luGuid, sbdProps->slp_guid, sizeof (sbdProps->slp_guid));
20459585STim.Szeto@Sun.COM 
20469585STim.Szeto@Sun.COM 	sbdIoctl.stmf_version = STMF_VERSION_1;
20479585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf_size = sbdPropsSize;
20489585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdProps;
20499585STim.Szeto@Sun.COM 	sbdIoctl.stmf_obuf_size = sbdPropsSize;
20509585STim.Szeto@Sun.COM 	sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdProps;
20519585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, SBD_IOCTL_GET_LU_PROPS, &sbdIoctl);
20529585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
20539585STim.Szeto@Sun.COM 		savedErrno = errno;
20549585STim.Szeto@Sun.COM 		switch (savedErrno) {
20559585STim.Szeto@Sun.COM 			case EBUSY:
20569585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
20579585STim.Szeto@Sun.COM 				break;
20589585STim.Szeto@Sun.COM 			case EPERM:
20599585STim.Szeto@Sun.COM 			case EACCES:
20609585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
20619585STim.Szeto@Sun.COM 				break;
20629585STim.Szeto@Sun.COM 			case ENOENT:
20639585STim.Szeto@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
20649585STim.Szeto@Sun.COM 				break;
20659585STim.Szeto@Sun.COM 			default:
20669585STim.Szeto@Sun.COM 				syslog(LOG_DEBUG,
20679585STim.Szeto@Sun.COM 				    "getDiskAllProps:ioctl error(%d) (%d) (%d)",
20689585STim.Szeto@Sun.COM 				    ioctlRet, sbdIoctl.stmf_error, savedErrno);
20699585STim.Szeto@Sun.COM 				ret = STMF_STATUS_ERROR;
20709585STim.Szeto@Sun.COM 				break;
20719585STim.Szeto@Sun.COM 		}
20729585STim.Szeto@Sun.COM 	}
20739585STim.Szeto@Sun.COM 
20749585STim.Szeto@Sun.COM 	if (ret == STMF_STATUS_SUCCESS) {
20759585STim.Szeto@Sun.COM 		ret = loadDiskPropsFromDriver((luResourceImpl *)*hdl, sbdProps);
20769585STim.Szeto@Sun.COM 	}
20779585STim.Szeto@Sun.COM 
20789585STim.Szeto@Sun.COM 	(void) close(fd);
20799585STim.Szeto@Sun.COM 	return (ret);
20809585STim.Szeto@Sun.COM }
20819585STim.Szeto@Sun.COM 
20829585STim.Szeto@Sun.COM /*
20839585STim.Szeto@Sun.COM  * loadDiskPropsFromDriver
20849585STim.Szeto@Sun.COM  *
20859585STim.Szeto@Sun.COM  * Purpose: Retrieve all disk type properties from sbd driver
20869585STim.Szeto@Sun.COM  *
20879585STim.Szeto@Sun.COM  * hdl - Allocated luResourceImpl
20889585STim.Szeto@Sun.COM  * sbdProps - sbd_lu_props_t structure returned from sbd driver
20899585STim.Szeto@Sun.COM  *
20909585STim.Szeto@Sun.COM  */
20919585STim.Szeto@Sun.COM static int
20929585STim.Szeto@Sun.COM loadDiskPropsFromDriver(luResourceImpl *hdl, sbd_lu_props_t *sbdProps)
20939585STim.Szeto@Sun.COM {
20949585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
20959585STim.Szeto@Sun.COM 	diskResource *diskLu = hdl->resource;
20969585STim.Szeto@Sun.COM 	/* copy guid */
20979585STim.Szeto@Sun.COM 	diskLu->luGuidValid = B_TRUE;
20989585STim.Szeto@Sun.COM 	bcopy(sbdProps->slp_guid, diskLu->luGuid, sizeof (sbdProps->slp_guid));
20999585STim.Szeto@Sun.COM 
21009585STim.Szeto@Sun.COM 	if (sbdProps->slp_separate_meta && sbdProps->slp_meta_fname_valid) {
21019585STim.Szeto@Sun.COM 		diskLu->luMetaFileNameValid = B_TRUE;
21029585STim.Szeto@Sun.COM 		if (strlcpy(diskLu->luMetaFileName,
21039585STim.Szeto@Sun.COM 		    (char *)&(sbdProps->slp_buf[sbdProps->slp_meta_fname_off]),
21049585STim.Szeto@Sun.COM 		    sizeof (diskLu->luMetaFileName)) >=
21059585STim.Szeto@Sun.COM 		    sizeof (diskLu->luMetaFileName)) {
21069585STim.Szeto@Sun.COM 			return (STMF_STATUS_ERROR);
21079585STim.Szeto@Sun.COM 		}
21089585STim.Szeto@Sun.COM 	}
21099585STim.Szeto@Sun.COM 
21109585STim.Szeto@Sun.COM 	if (sbdProps->slp_data_fname_valid) {
21119585STim.Szeto@Sun.COM 		diskLu->luDataFileNameValid = B_TRUE;
21129585STim.Szeto@Sun.COM 		if (strlcpy(diskLu->luDataFileName,
21139585STim.Szeto@Sun.COM 		    (char *)&(sbdProps->slp_buf[sbdProps->slp_data_fname_off]),
21149585STim.Szeto@Sun.COM 		    sizeof (diskLu->luDataFileName)) >=
21159585STim.Szeto@Sun.COM 		    sizeof (diskLu->luDataFileName)) {
21169585STim.Szeto@Sun.COM 			return (STMF_STATUS_ERROR);
21179585STim.Szeto@Sun.COM 		}
21189585STim.Szeto@Sun.COM 	}
21199585STim.Szeto@Sun.COM 
21209585STim.Szeto@Sun.COM 	if (sbdProps->slp_serial_valid) {
21219585STim.Szeto@Sun.COM 		diskLu->serialNumValid = B_TRUE;
21229585STim.Szeto@Sun.COM 		bcopy(&(sbdProps->slp_buf[sbdProps->slp_serial_off]),
21239585STim.Szeto@Sun.COM 		    diskLu->serialNum, sbdProps->slp_serial_size);
21249585STim.Szeto@Sun.COM 	}
21259585STim.Szeto@Sun.COM 
21269585STim.Szeto@Sun.COM 	if (sbdProps->slp_alias_valid) {
21279585STim.Szeto@Sun.COM 		diskLu->luAliasValid = B_TRUE;
21289585STim.Szeto@Sun.COM 		if (strlcpy(diskLu->luAlias,
21299585STim.Szeto@Sun.COM 		    (char *)&(sbdProps->slp_buf[sbdProps->slp_alias_off]),
21309585STim.Szeto@Sun.COM 		    sizeof (diskLu->luAlias)) >=
21319585STim.Szeto@Sun.COM 		    sizeof (diskLu->luAlias)) {
21329585STim.Szeto@Sun.COM 			return (STMF_STATUS_ERROR);
21339585STim.Szeto@Sun.COM 		}
21349585STim.Szeto@Sun.COM 	} else { /* set alias to data filename if not set */
21359585STim.Szeto@Sun.COM 		if (sbdProps->slp_data_fname_valid) {
21369585STim.Szeto@Sun.COM 			diskLu->luAliasValid = B_TRUE;
21379585STim.Szeto@Sun.COM 			if (strlcpy(diskLu->luAlias,
21389585STim.Szeto@Sun.COM 			    (char *)&(sbdProps->slp_buf[
21399585STim.Szeto@Sun.COM 			    sbdProps->slp_data_fname_off]),
21409585STim.Szeto@Sun.COM 			    sizeof (diskLu->luAlias)) >=
21419585STim.Szeto@Sun.COM 			    sizeof (diskLu->luAlias)) {
21429585STim.Szeto@Sun.COM 				return (STMF_STATUS_ERROR);
21439585STim.Szeto@Sun.COM 			}
21449585STim.Szeto@Sun.COM 		}
21459585STim.Szeto@Sun.COM 	}
21469585STim.Szeto@Sun.COM 
21479585STim.Szeto@Sun.COM 	diskLu->vidValid = B_TRUE;
21489585STim.Szeto@Sun.COM 	bcopy(sbdProps->slp_vid, diskLu->vid, sizeof (diskLu->vid));
21499585STim.Szeto@Sun.COM 
21509585STim.Szeto@Sun.COM 	diskLu->pidValid = B_TRUE;
21519585STim.Szeto@Sun.COM 	bcopy(sbdProps->slp_pid, diskLu->pid, sizeof (diskLu->pid));
21529585STim.Szeto@Sun.COM 
21539585STim.Szeto@Sun.COM 	diskLu->revValid = B_TRUE;
21549585STim.Szeto@Sun.COM 	bcopy(sbdProps->slp_rev, diskLu->rev, sizeof (diskLu->rev));
21559585STim.Szeto@Sun.COM 
21569585STim.Szeto@Sun.COM 	diskLu->writeProtectEnableValid = B_TRUE;
21579585STim.Szeto@Sun.COM 	if (sbdProps->slp_write_protected) {
21589585STim.Szeto@Sun.COM 		diskLu->writeProtectEnable = B_TRUE;
21599585STim.Szeto@Sun.COM 	}
21609585STim.Szeto@Sun.COM 
21619585STim.Szeto@Sun.COM 	diskLu->writebackCacheDisableValid = B_TRUE;
21629585STim.Szeto@Sun.COM 	if (sbdProps->slp_writeback_cache_disable_cur) {
21639585STim.Szeto@Sun.COM 		diskLu->writebackCacheDisable = B_TRUE;
21649585STim.Szeto@Sun.COM 	}
21659585STim.Szeto@Sun.COM 
21669585STim.Szeto@Sun.COM 	diskLu->blkSizeValid = B_TRUE;
21679585STim.Szeto@Sun.COM 	diskLu->blkSize = sbdProps->slp_blksize;
21689585STim.Szeto@Sun.COM 
21699585STim.Szeto@Sun.COM 	diskLu->luSizeValid = B_TRUE;
21709585STim.Szeto@Sun.COM 	diskLu->luSize = sbdProps->slp_lu_size;
21719585STim.Szeto@Sun.COM 
21729585STim.Szeto@Sun.COM 	return (ret);
21739585STim.Szeto@Sun.COM }
21749585STim.Szeto@Sun.COM 
21759585STim.Szeto@Sun.COM 
21769585STim.Szeto@Sun.COM /*
21779585STim.Szeto@Sun.COM  * stmfSetLuProp
21789585STim.Szeto@Sun.COM  *
21799585STim.Szeto@Sun.COM  * Purpose: set a property on an luResource
21809585STim.Szeto@Sun.COM  *
21819585STim.Szeto@Sun.COM  * hdl - allocated luResource
21829585STim.Szeto@Sun.COM  * prop - property identifier
21839585STim.Szeto@Sun.COM  * propVal - property value to be set
21849585STim.Szeto@Sun.COM  */
21859585STim.Szeto@Sun.COM int
21869585STim.Szeto@Sun.COM stmfSetLuProp(luResource hdl, uint32_t prop, const char *propVal)
21879585STim.Szeto@Sun.COM {
21889585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
21899585STim.Szeto@Sun.COM 	luResourceImpl *luPropsHdl = hdl;
21909585STim.Szeto@Sun.COM 	if (hdl == NULL) {
21919585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
21929585STim.Szeto@Sun.COM 	}
21939585STim.Szeto@Sun.COM 
21949585STim.Szeto@Sun.COM 	if (luPropsHdl->type == STMF_DISK) {
21959585STim.Szeto@Sun.COM 		ret = setDiskProp(luPropsHdl, prop, propVal);
21969585STim.Szeto@Sun.COM 	} else {
21979585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
21989585STim.Szeto@Sun.COM 	}
21999585STim.Szeto@Sun.COM 
22009585STim.Szeto@Sun.COM 	return (ret);
22019585STim.Szeto@Sun.COM }
22029585STim.Szeto@Sun.COM 
22039585STim.Szeto@Sun.COM /*
22049585STim.Szeto@Sun.COM  * getDiskProp
22059585STim.Szeto@Sun.COM  *
22069585STim.Szeto@Sun.COM  * Purpose: retrieve a given property from a logical unit resource of type disk
22079585STim.Szeto@Sun.COM  *
22089585STim.Szeto@Sun.COM  * hdl - allocated luResourceImpl
22099585STim.Szeto@Sun.COM  * prop - property identifier
22109585STim.Szeto@Sun.COM  * propVal - pointer to character to contain the retrieved property value
22119585STim.Szeto@Sun.COM  * propLen - On input this is the length of propVal. On failure, it contains the
22129585STim.Szeto@Sun.COM  *           number of bytes required for propVal
22139585STim.Szeto@Sun.COM  */
22149585STim.Szeto@Sun.COM static int
22159585STim.Szeto@Sun.COM getDiskProp(luResourceImpl *hdl, uint32_t prop, char *propVal, size_t *propLen)
22169585STim.Szeto@Sun.COM {
22179585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
22189585STim.Szeto@Sun.COM 	diskResource *diskLu = hdl->resource;
22199585STim.Szeto@Sun.COM 	size_t reqLen;
22209585STim.Szeto@Sun.COM 
22219585STim.Szeto@Sun.COM 	switch (prop) {
22229585STim.Szeto@Sun.COM 		case STMF_LU_PROP_BLOCK_SIZE:
22239585STim.Szeto@Sun.COM 			if (diskLu->blkSizeValid == B_FALSE) {
22249585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
22259585STim.Szeto@Sun.COM 			}
22269585STim.Szeto@Sun.COM 			reqLen = snprintf(propVal, *propLen, "%llu",
22279585STim.Szeto@Sun.COM 			    (u_longlong_t)diskLu->blkSize);
22289585STim.Szeto@Sun.COM 			if (reqLen >= *propLen) {
22299585STim.Szeto@Sun.COM 				*propLen = reqLen + 1;
22309585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
22319585STim.Szeto@Sun.COM 			}
22329585STim.Szeto@Sun.COM 			break;
22339585STim.Szeto@Sun.COM 		case STMF_LU_PROP_FILENAME:
22349585STim.Szeto@Sun.COM 			if (diskLu->luDataFileNameValid == B_FALSE) {
22359585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
22369585STim.Szeto@Sun.COM 			}
22379585STim.Szeto@Sun.COM 			if ((reqLen = strlcpy(propVal, diskLu->luDataFileName,
22389585STim.Szeto@Sun.COM 			    *propLen)) >= *propLen) {
22399585STim.Szeto@Sun.COM 				*propLen = reqLen + 1;
22409585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
22419585STim.Szeto@Sun.COM 			}
22429585STim.Szeto@Sun.COM 			break;
22439585STim.Szeto@Sun.COM 		case STMF_LU_PROP_META_FILENAME:
22449585STim.Szeto@Sun.COM 			if (diskLu->luMetaFileNameValid == B_FALSE) {
22459585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
22469585STim.Szeto@Sun.COM 			}
22479585STim.Szeto@Sun.COM 			if ((reqLen = strlcpy(propVal, diskLu->luMetaFileName,
22489585STim.Szeto@Sun.COM 			    *propLen)) >= *propLen) {
22499585STim.Szeto@Sun.COM 				*propLen = reqLen + 1;
22509585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
22519585STim.Szeto@Sun.COM 			}
22529585STim.Szeto@Sun.COM 			break;
22539585STim.Szeto@Sun.COM 		case STMF_LU_PROP_GUID:
22549585STim.Szeto@Sun.COM 			if (diskLu->luGuidValid == B_FALSE) {
22559585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
22569585STim.Szeto@Sun.COM 			}
22579585STim.Szeto@Sun.COM 			reqLen = snprintf(propVal, *propLen,
22589585STim.Szeto@Sun.COM 			    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X"
22599585STim.Szeto@Sun.COM 			    "%02X%02X%02X%02X",
22609585STim.Szeto@Sun.COM 			    diskLu->luGuid[0], diskLu->luGuid[1],
22619585STim.Szeto@Sun.COM 			    diskLu->luGuid[2], diskLu->luGuid[3],
22629585STim.Szeto@Sun.COM 			    diskLu->luGuid[4], diskLu->luGuid[5],
22639585STim.Szeto@Sun.COM 			    diskLu->luGuid[6], diskLu->luGuid[7],
22649585STim.Szeto@Sun.COM 			    diskLu->luGuid[8], diskLu->luGuid[9],
22659585STim.Szeto@Sun.COM 			    diskLu->luGuid[10], diskLu->luGuid[11],
22669585STim.Szeto@Sun.COM 			    diskLu->luGuid[12], diskLu->luGuid[13],
22679585STim.Szeto@Sun.COM 			    diskLu->luGuid[14], diskLu->luGuid[15]);
22689585STim.Szeto@Sun.COM 			if (reqLen >= *propLen) {
22699585STim.Szeto@Sun.COM 				*propLen = reqLen + 1;
22709585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
22719585STim.Szeto@Sun.COM 			}
22729585STim.Szeto@Sun.COM 			break;
22739585STim.Szeto@Sun.COM 		case STMF_LU_PROP_SERIAL_NUM:
22749585STim.Szeto@Sun.COM 			if (diskLu->serialNumValid == B_FALSE) {
22759585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
22769585STim.Szeto@Sun.COM 			}
22779585STim.Szeto@Sun.COM 			if ((reqLen = strlcpy(propVal, diskLu->serialNum,
22789585STim.Szeto@Sun.COM 			    *propLen)) >= *propLen) {
22799585STim.Szeto@Sun.COM 				*propLen = reqLen + 1;
22809585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
22819585STim.Szeto@Sun.COM 			}
22829585STim.Szeto@Sun.COM 			break;
22839585STim.Szeto@Sun.COM 		case STMF_LU_PROP_SIZE:
22849585STim.Szeto@Sun.COM 			if (diskLu->luSizeValid == B_FALSE) {
22859585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
22869585STim.Szeto@Sun.COM 			}
22879585STim.Szeto@Sun.COM 			(void) snprintf(propVal, *propLen, "%llu",
22889585STim.Szeto@Sun.COM 			    (u_longlong_t)diskLu->luSize);
22899585STim.Szeto@Sun.COM 			break;
22909585STim.Szeto@Sun.COM 		case STMF_LU_PROP_ALIAS:
22919585STim.Szeto@Sun.COM 			if (diskLu->luAliasValid == B_FALSE) {
22929585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
22939585STim.Szeto@Sun.COM 			}
22949585STim.Szeto@Sun.COM 			if ((reqLen = strlcpy(propVal, diskLu->luAlias,
22959585STim.Szeto@Sun.COM 			    *propLen)) >= *propLen) {
22969585STim.Szeto@Sun.COM 				*propLen = reqLen + 1;
22979585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
22989585STim.Szeto@Sun.COM 			}
22999585STim.Szeto@Sun.COM 			break;
23009585STim.Szeto@Sun.COM 		case STMF_LU_PROP_VID:
23019585STim.Szeto@Sun.COM 			if (diskLu->vidValid == B_FALSE) {
23029585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
23039585STim.Szeto@Sun.COM 			}
23049585STim.Szeto@Sun.COM 			if (*propLen <= sizeof (diskLu->vid)) {
23059585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
23069585STim.Szeto@Sun.COM 			}
23079585STim.Szeto@Sun.COM 			bcopy(diskLu->vid, propVal, sizeof (diskLu->vid));
23089585STim.Szeto@Sun.COM 			propVal[sizeof (diskLu->vid)] = 0;
23099585STim.Szeto@Sun.COM 			break;
23109585STim.Szeto@Sun.COM 		case STMF_LU_PROP_PID:
23119585STim.Szeto@Sun.COM 			if (diskLu->pidValid == B_FALSE) {
23129585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
23139585STim.Szeto@Sun.COM 			}
23149585STim.Szeto@Sun.COM 			if (*propLen <= sizeof (diskLu->pid)) {
23159585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
23169585STim.Szeto@Sun.COM 			}
23179585STim.Szeto@Sun.COM 			bcopy(diskLu->pid, propVal, sizeof (diskLu->pid));
23189585STim.Szeto@Sun.COM 			propVal[sizeof (diskLu->pid)] = 0;
23199585STim.Szeto@Sun.COM 			break;
23209585STim.Szeto@Sun.COM 		case STMF_LU_PROP_WRITE_PROTECT:
23219585STim.Szeto@Sun.COM 			if (diskLu->writeProtectEnableValid == B_FALSE) {
23229585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
23239585STim.Szeto@Sun.COM 			}
23249585STim.Szeto@Sun.COM 			if (diskLu->writeProtectEnable) {
23259585STim.Szeto@Sun.COM 				if ((reqLen = strlcpy(propVal, "true",
23269585STim.Szeto@Sun.COM 				    *propLen)) >= *propLen) {
23279585STim.Szeto@Sun.COM 					*propLen = reqLen + 1;
23289585STim.Szeto@Sun.COM 					return (STMF_ERROR_INVALID_ARG);
23299585STim.Szeto@Sun.COM 				}
23309585STim.Szeto@Sun.COM 			} else {
23319585STim.Szeto@Sun.COM 				if ((reqLen = strlcpy(propVal, "false",
23329585STim.Szeto@Sun.COM 				    *propLen)) >= *propLen) {
23339585STim.Szeto@Sun.COM 					*propLen = reqLen + 1;
23349585STim.Szeto@Sun.COM 					return (STMF_ERROR_INVALID_ARG);
23359585STim.Szeto@Sun.COM 				}
23369585STim.Szeto@Sun.COM 			}
23379585STim.Szeto@Sun.COM 			break;
23389585STim.Szeto@Sun.COM 		case STMF_LU_PROP_WRITE_CACHE_DISABLE:
23399585STim.Szeto@Sun.COM 			if (diskLu->writebackCacheDisableValid == B_FALSE) {
23409585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
23419585STim.Szeto@Sun.COM 			}
23429585STim.Szeto@Sun.COM 			if (diskLu->writebackCacheDisable) {
23439585STim.Szeto@Sun.COM 				if ((reqLen = strlcpy(propVal, "true",
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 			} else {
23499585STim.Szeto@Sun.COM 				if ((reqLen = strlcpy(propVal, "false",
23509585STim.Szeto@Sun.COM 				    *propLen)) >= *propLen) {
23519585STim.Szeto@Sun.COM 					*propLen = reqLen + 1;
23529585STim.Szeto@Sun.COM 					return (STMF_ERROR_INVALID_ARG);
23539585STim.Szeto@Sun.COM 				}
23549585STim.Szeto@Sun.COM 			}
23559585STim.Szeto@Sun.COM 			break;
23569585STim.Szeto@Sun.COM 		default:
23579585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NO_PROP;
23589585STim.Szeto@Sun.COM 			break;
23599585STim.Szeto@Sun.COM 	}
23609585STim.Szeto@Sun.COM 
23619585STim.Szeto@Sun.COM 	return (ret);
23629585STim.Szeto@Sun.COM }
23639585STim.Szeto@Sun.COM 
23649585STim.Szeto@Sun.COM /*
23659585STim.Szeto@Sun.COM  * setDiskProp
23669585STim.Szeto@Sun.COM  *
23679585STim.Szeto@Sun.COM  * Purpose: set properties for resource of type disk
23689585STim.Szeto@Sun.COM  *
23699585STim.Szeto@Sun.COM  * hdl - allocated luResourceImpl
23709585STim.Szeto@Sun.COM  * resourceProp - valid resource identifier
23719585STim.Szeto@Sun.COM  * propVal - valid resource value
23729585STim.Szeto@Sun.COM  */
23739585STim.Szeto@Sun.COM static int
23749585STim.Szeto@Sun.COM setDiskProp(luResourceImpl *hdl, uint32_t resourceProp, const char *propVal)
23759585STim.Szeto@Sun.COM {
23769585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
23779585STim.Szeto@Sun.COM 	int i;
23789585STim.Szeto@Sun.COM 	diskResource *diskLu = hdl->resource;
23799585STim.Szeto@Sun.COM 	unsigned long long numericProp = 0;
23809585STim.Szeto@Sun.COM 	char guidProp[LU_ASCII_GUID_SIZE + 1];
23819585STim.Szeto@Sun.COM 	char ouiProp[OUI_ASCII_SIZE + 1];
23829585STim.Szeto@Sun.COM 	unsigned int oui[OUI_SIZE];
23839585STim.Szeto@Sun.COM 	unsigned int guid[LU_GUID_SIZE];
23849585STim.Szeto@Sun.COM 	int propSize;
23859585STim.Szeto@Sun.COM 
23869585STim.Szeto@Sun.COM 
23879585STim.Szeto@Sun.COM 	if (propVal == NULL) {
23889585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
23899585STim.Szeto@Sun.COM 	}
23909585STim.Szeto@Sun.COM 
23919585STim.Szeto@Sun.COM 	switch (resourceProp) {
23929585STim.Szeto@Sun.COM 		case STMF_LU_PROP_ALIAS:
23939585STim.Szeto@Sun.COM 			if (strlcpy(diskLu->luAlias, propVal,
23949585STim.Szeto@Sun.COM 			    sizeof (diskLu->luAlias)) >=
23959585STim.Szeto@Sun.COM 			    sizeof (diskLu->luAlias)) {
23969585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
23979585STim.Szeto@Sun.COM 			}
23989585STim.Szeto@Sun.COM 			diskLu->luAliasValid = B_TRUE;
23999585STim.Szeto@Sun.COM 			break;
24009585STim.Szeto@Sun.COM 		case STMF_LU_PROP_BLOCK_SIZE:
24019585STim.Szeto@Sun.COM 			(void) sscanf(propVal, "%llu", &numericProp);
24029585STim.Szeto@Sun.COM 			if (numericProp > UINT16_MAX) {
24039585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
24049585STim.Szeto@Sun.COM 			}
24059585STim.Szeto@Sun.COM 			diskLu->blkSize = numericProp;
24069585STim.Szeto@Sun.COM 			diskLu->blkSizeValid = B_TRUE;
24079585STim.Szeto@Sun.COM 			break;
24089585STim.Szeto@Sun.COM 		case STMF_LU_PROP_COMPANY_ID:
24099585STim.Szeto@Sun.COM 			if ((strlcpy(ouiProp, propVal, sizeof (ouiProp))) >=
24109585STim.Szeto@Sun.COM 			    sizeof (ouiProp)) {
24119585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
24129585STim.Szeto@Sun.COM 			}
24139585STim.Szeto@Sun.COM 			if (checkHexUpper(ouiProp) != 0) {
24149585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
24159585STim.Szeto@Sun.COM 			}
24169585STim.Szeto@Sun.COM 			(void) sscanf(ouiProp, "%2X%2X%2X",
24179585STim.Szeto@Sun.COM 			    &oui[0], &oui[1], &oui[2]);
24189585STim.Szeto@Sun.COM 
24199585STim.Szeto@Sun.COM 			diskLu->companyId = 0;
24209585STim.Szeto@Sun.COM 			diskLu->companyId += oui[0] << 16;
24219585STim.Szeto@Sun.COM 			diskLu->companyId += oui[1] << 8;
24229585STim.Szeto@Sun.COM 			diskLu->companyId += oui[2];
24239585STim.Szeto@Sun.COM 			diskLu->companyIdValid = B_TRUE;
24249585STim.Szeto@Sun.COM 			break;
24259585STim.Szeto@Sun.COM 		case STMF_LU_PROP_GUID:
24269585STim.Szeto@Sun.COM 			if (strlen(propVal) != LU_ASCII_GUID_SIZE) {
24279585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
24289585STim.Szeto@Sun.COM 			}
24299585STim.Szeto@Sun.COM 
24309585STim.Szeto@Sun.COM 			if ((strlcpy(guidProp, propVal, sizeof (guidProp))) >=
24319585STim.Szeto@Sun.COM 			    sizeof (guidProp)) {
24329585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
24339585STim.Szeto@Sun.COM 			}
24349585STim.Szeto@Sun.COM 
24359585STim.Szeto@Sun.COM 			if (checkHexUpper(guidProp) != 0) {
24369585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
24379585STim.Szeto@Sun.COM 			}
24389585STim.Szeto@Sun.COM 
24399585STim.Szeto@Sun.COM 			(void) sscanf(guidProp,
24409585STim.Szeto@Sun.COM 			    "%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X",
24419585STim.Szeto@Sun.COM 			    &guid[0], &guid[1], &guid[2], &guid[3], &guid[4],
24429585STim.Szeto@Sun.COM 			    &guid[5], &guid[6], &guid[7], &guid[8], &guid[9],
24439585STim.Szeto@Sun.COM 			    &guid[10], &guid[11], &guid[12], &guid[13],
24449585STim.Szeto@Sun.COM 			    &guid[14], &guid[15]);
24459585STim.Szeto@Sun.COM 			for (i = 0; i < sizeof (diskLu->luGuid); i++) {
24469585STim.Szeto@Sun.COM 				diskLu->luGuid[i] = guid[i];
24479585STim.Szeto@Sun.COM 			}
24489585STim.Szeto@Sun.COM 			diskLu->luGuidValid = B_TRUE;
24499585STim.Szeto@Sun.COM 			break;
24509585STim.Szeto@Sun.COM 		case STMF_LU_PROP_FILENAME:
24519585STim.Szeto@Sun.COM 			if ((strlcpy(diskLu->luDataFileName, propVal,
24529585STim.Szeto@Sun.COM 			    sizeof (diskLu->luDataFileName))) >=
24539585STim.Szeto@Sun.COM 			    sizeof (diskLu->luDataFileName)) {
24549585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
24559585STim.Szeto@Sun.COM 			}
24569585STim.Szeto@Sun.COM 			diskLu->luDataFileNameValid = B_TRUE;
24579585STim.Szeto@Sun.COM 			break;
24589585STim.Szeto@Sun.COM 		case STMF_LU_PROP_META_FILENAME:
24599585STim.Szeto@Sun.COM 			if ((strlcpy(diskLu->luMetaFileName, propVal,
24609585STim.Szeto@Sun.COM 			    sizeof (diskLu->luMetaFileName))) >=
24619585STim.Szeto@Sun.COM 			    sizeof (diskLu->luMetaFileName)) {
24629585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
24639585STim.Szeto@Sun.COM 			}
24649585STim.Szeto@Sun.COM 			diskLu->luMetaFileNameValid = B_TRUE;
24659585STim.Szeto@Sun.COM 			break;
24669585STim.Szeto@Sun.COM 		case STMF_LU_PROP_PID:
24679585STim.Szeto@Sun.COM 			if ((propSize = strlen(propVal)) >
24689585STim.Szeto@Sun.COM 			    sizeof (diskLu->pid)) {
24699585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
24709585STim.Szeto@Sun.COM 			}
24719585STim.Szeto@Sun.COM 			(void) strncpy(diskLu->pid, propVal, propSize);
24729585STim.Szeto@Sun.COM 			diskLu->pidValid = B_TRUE;
24739585STim.Szeto@Sun.COM 			break;
24749585STim.Szeto@Sun.COM 		case STMF_LU_PROP_SERIAL_NUM:
24759585STim.Szeto@Sun.COM 			if ((propSize = strlen(propVal)) >
24769585STim.Szeto@Sun.COM 			    (sizeof (diskLu->serialNum) - 1)) {
24779585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
24789585STim.Szeto@Sun.COM 			}
24799585STim.Szeto@Sun.COM 			(void) strncpy(diskLu->serialNum, propVal, propSize);
24809585STim.Szeto@Sun.COM 			diskLu->serialNumValid = B_TRUE;
24819585STim.Szeto@Sun.COM 			break;
24829585STim.Szeto@Sun.COM 		case STMF_LU_PROP_SIZE:
24839585STim.Szeto@Sun.COM 			if ((niceStrToNum(propVal, &diskLu->luSize) != 0)) {
24849585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
24859585STim.Szeto@Sun.COM 			}
24869585STim.Szeto@Sun.COM 			diskLu->luSizeValid = B_TRUE;
24879585STim.Szeto@Sun.COM 			break;
24889585STim.Szeto@Sun.COM 		case STMF_LU_PROP_VID:
24899585STim.Szeto@Sun.COM 			if ((propSize = strlen(propVal)) >
24909585STim.Szeto@Sun.COM 			    sizeof (diskLu->vid)) {
24919585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
24929585STim.Szeto@Sun.COM 			}
24939585STim.Szeto@Sun.COM 			(void) strncpy(diskLu->vid, propVal, propSize);
24949585STim.Szeto@Sun.COM 			diskLu->vidValid = B_TRUE;
24959585STim.Szeto@Sun.COM 			break;
24969585STim.Szeto@Sun.COM 		case STMF_LU_PROP_WRITE_PROTECT:
24979585STim.Szeto@Sun.COM 			if (strcasecmp(propVal, "TRUE") == 0) {
24989585STim.Szeto@Sun.COM 				diskLu->writeProtectEnable = B_TRUE;
24999585STim.Szeto@Sun.COM 			} else if (strcasecmp(propVal, "FALSE") == 0) {
25009585STim.Szeto@Sun.COM 				diskLu->writeProtectEnable = B_FALSE;
25019585STim.Szeto@Sun.COM 			} else {
25029585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
25039585STim.Szeto@Sun.COM 			}
25049585STim.Szeto@Sun.COM 			diskLu->writeProtectEnableValid = B_TRUE;
25059585STim.Szeto@Sun.COM 			break;
25069585STim.Szeto@Sun.COM 		case STMF_LU_PROP_WRITE_CACHE_DISABLE:
25079585STim.Szeto@Sun.COM 			if (strcasecmp(propVal, "TRUE") == 0) {
25089585STim.Szeto@Sun.COM 				diskLu->writebackCacheDisable = B_TRUE;
25099585STim.Szeto@Sun.COM 			} else if (strcasecmp(propVal, "FALSE") == 0) {
25109585STim.Szeto@Sun.COM 				diskLu->writebackCacheDisable = B_FALSE;
25119585STim.Szeto@Sun.COM 			} else {
25129585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
25139585STim.Szeto@Sun.COM 			}
25149585STim.Szeto@Sun.COM 			diskLu->writebackCacheDisableValid = B_TRUE;
25159585STim.Szeto@Sun.COM 			break;
25169585STim.Szeto@Sun.COM 		default:
25179585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NO_PROP;
25189585STim.Szeto@Sun.COM 			break;
25199585STim.Szeto@Sun.COM 	}
25209585STim.Szeto@Sun.COM 	return (ret);
25219585STim.Szeto@Sun.COM }
25229585STim.Szeto@Sun.COM 
25239585STim.Szeto@Sun.COM static int
25249585STim.Szeto@Sun.COM checkHexUpper(char *buf)
25259585STim.Szeto@Sun.COM {
25269585STim.Szeto@Sun.COM 	int i;
25279585STim.Szeto@Sun.COM 
25289585STim.Szeto@Sun.COM 	for (i = 0; i < strlen(buf); i++) {
25299585STim.Szeto@Sun.COM 		if (isxdigit(buf[i])) {
25309585STim.Szeto@Sun.COM 			buf[i] = toupper(buf[i]);
25319585STim.Szeto@Sun.COM 			continue;
25329585STim.Szeto@Sun.COM 		}
25339585STim.Szeto@Sun.COM 		return (-1);
25349585STim.Szeto@Sun.COM 	}
25359585STim.Szeto@Sun.COM 
25369585STim.Szeto@Sun.COM 	return (0);
25379585STim.Szeto@Sun.COM }
25389585STim.Szeto@Sun.COM 
25399585STim.Szeto@Sun.COM /*
25409585STim.Szeto@Sun.COM  * Given a numeric suffix, convert the value into a number of bits that the
25419585STim.Szeto@Sun.COM  * resulting value must be shifted.
25429585STim.Szeto@Sun.COM  * Code lifted from libzfs_util.c
25439585STim.Szeto@Sun.COM  */
25449585STim.Szeto@Sun.COM static int
25459585STim.Szeto@Sun.COM strToShift(const char *buf)
25469585STim.Szeto@Sun.COM {
25479585STim.Szeto@Sun.COM 	const char *ends = "BKMGTPE";
25489585STim.Szeto@Sun.COM 	int i;
25499585STim.Szeto@Sun.COM 
25509585STim.Szeto@Sun.COM 	if (buf[0] == '\0')
25519585STim.Szeto@Sun.COM 		return (0);
25529585STim.Szeto@Sun.COM 
25539585STim.Szeto@Sun.COM 	for (i = 0; i < strlen(ends); i++) {
25549585STim.Szeto@Sun.COM 		if (toupper(buf[0]) == ends[i])
25559585STim.Szeto@Sun.COM 			return (10*i);
25569585STim.Szeto@Sun.COM 	}
25579585STim.Szeto@Sun.COM 
25589585STim.Szeto@Sun.COM 	return (-1);
25599585STim.Szeto@Sun.COM }
25609585STim.Szeto@Sun.COM 
25619585STim.Szeto@Sun.COM int
25629585STim.Szeto@Sun.COM stmfFreeLuResource(luResource hdl)
25639585STim.Szeto@Sun.COM {
25649585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
25659585STim.Szeto@Sun.COM 	if (hdl == NULL) {
25669585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
25679585STim.Szeto@Sun.COM 	}
25689585STim.Szeto@Sun.COM 
25699585STim.Szeto@Sun.COM 	luResourceImpl *hdlImpl = hdl;
25709585STim.Szeto@Sun.COM 	free(hdlImpl->resource);
25719585STim.Szeto@Sun.COM 	free(hdlImpl);
25729585STim.Szeto@Sun.COM 	return (ret);
25739585STim.Szeto@Sun.COM }
25749585STim.Szeto@Sun.COM 
25759585STim.Szeto@Sun.COM /*
25769585STim.Szeto@Sun.COM  * Convert a string of the form '100G' into a real number. Used when setting
25779585STim.Szeto@Sun.COM  * the size of a logical unit.
25789585STim.Szeto@Sun.COM  * Code lifted from libzfs_util.c
25799585STim.Szeto@Sun.COM  */
25809585STim.Szeto@Sun.COM static int
25819585STim.Szeto@Sun.COM niceStrToNum(const char *value, uint64_t *num)
25829585STim.Szeto@Sun.COM {
25839585STim.Szeto@Sun.COM 	char *end;
25849585STim.Szeto@Sun.COM 	int shift;
25859585STim.Szeto@Sun.COM 
25869585STim.Szeto@Sun.COM 	*num = 0;
25879585STim.Szeto@Sun.COM 
25889585STim.Szeto@Sun.COM 	/* Check to see if this looks like a number.  */
25899585STim.Szeto@Sun.COM 	if ((value[0] < '0' || value[0] > '9') && value[0] != '.') {
25909585STim.Szeto@Sun.COM 		return (-1);
25919585STim.Szeto@Sun.COM 	}
25929585STim.Szeto@Sun.COM 
25939585STim.Szeto@Sun.COM 	/* Rely on stroull() to process the numeric portion.  */
25949585STim.Szeto@Sun.COM 	errno = 0;
25959585STim.Szeto@Sun.COM 	*num = strtoull(value, &end, 10);
25969585STim.Szeto@Sun.COM 
25979585STim.Szeto@Sun.COM 	/*
25989585STim.Szeto@Sun.COM 	 * Check for ERANGE, which indicates that the value is too large to fit
25999585STim.Szeto@Sun.COM 	 * in a 64-bit value.
26009585STim.Szeto@Sun.COM 	 */
26019585STim.Szeto@Sun.COM 	if (errno == ERANGE) {
26029585STim.Szeto@Sun.COM 		return (-1);
26039585STim.Szeto@Sun.COM 	}
26049585STim.Szeto@Sun.COM 
26059585STim.Szeto@Sun.COM 	/*
26069585STim.Szeto@Sun.COM 	 * If we have a decimal value, then do the computation with floating
26079585STim.Szeto@Sun.COM 	 * point arithmetic.  Otherwise, use standard arithmetic.
26089585STim.Szeto@Sun.COM 	 */
26099585STim.Szeto@Sun.COM 	if (*end == '.') {
26109585STim.Szeto@Sun.COM 		double fval = strtod(value, &end);
26119585STim.Szeto@Sun.COM 
26129585STim.Szeto@Sun.COM 		if ((shift = strToShift(end)) == -1) {
26139585STim.Szeto@Sun.COM 			return (-1);
26149585STim.Szeto@Sun.COM 		}
26159585STim.Szeto@Sun.COM 
26169585STim.Szeto@Sun.COM 		fval *= pow(2, shift);
26179585STim.Szeto@Sun.COM 
26189585STim.Szeto@Sun.COM 		if (fval > UINT64_MAX) {
26199585STim.Szeto@Sun.COM 			return (-1);
26209585STim.Szeto@Sun.COM 		}
26219585STim.Szeto@Sun.COM 
26229585STim.Szeto@Sun.COM 		*num = (uint64_t)fval;
26239585STim.Szeto@Sun.COM 	} else {
26249585STim.Szeto@Sun.COM 		if ((shift = strToShift(end)) == -1) {
26259585STim.Szeto@Sun.COM 			return (-1);
26269585STim.Szeto@Sun.COM 		}
26279585STim.Szeto@Sun.COM 
26289585STim.Szeto@Sun.COM 		/* Check for overflow */
26299585STim.Szeto@Sun.COM 		if (shift >= 64 || (*num << shift) >> shift != *num) {
26309585STim.Szeto@Sun.COM 			return (-1);
26319585STim.Szeto@Sun.COM 		}
26329585STim.Szeto@Sun.COM 
26339585STim.Szeto@Sun.COM 		*num <<= shift;
26349585STim.Szeto@Sun.COM 	}
26359585STim.Szeto@Sun.COM 
26369585STim.Szeto@Sun.COM 	return (0);
26379585STim.Szeto@Sun.COM }
26389585STim.Szeto@Sun.COM 
26399585STim.Szeto@Sun.COM /*
26407836SJohn.Forte@Sun.COM  * stmfCreateTargetGroup
26417836SJohn.Forte@Sun.COM  *
26427836SJohn.Forte@Sun.COM  * Purpose: Create a local port group
26437836SJohn.Forte@Sun.COM  *
26447836SJohn.Forte@Sun.COM  * targetGroupName - name of local port group to create
26457836SJohn.Forte@Sun.COM  */
26467836SJohn.Forte@Sun.COM int
26477836SJohn.Forte@Sun.COM stmfCreateTargetGroup(stmfGroupName *targetGroupName)
26487836SJohn.Forte@Sun.COM {
26497836SJohn.Forte@Sun.COM 	int ret;
26507836SJohn.Forte@Sun.COM 	int fd;
26517836SJohn.Forte@Sun.COM 
26527836SJohn.Forte@Sun.COM 	if (targetGroupName == NULL ||
26537836SJohn.Forte@Sun.COM 	    (strnlen((char *)targetGroupName, sizeof (stmfGroupName))
26547836SJohn.Forte@Sun.COM 	    == sizeof (stmfGroupName))) {
26557836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
26567836SJohn.Forte@Sun.COM 	}
26577836SJohn.Forte@Sun.COM 
26587836SJohn.Forte@Sun.COM 	/* Check to ensure service exists */
26597836SJohn.Forte@Sun.COM 	if (psCheckService() != STMF_STATUS_SUCCESS) {
26607836SJohn.Forte@Sun.COM 		return (STMF_ERROR_SERVICE_NOT_FOUND);
26617836SJohn.Forte@Sun.COM 	}
26627836SJohn.Forte@Sun.COM 
26637836SJohn.Forte@Sun.COM 	/* call init */
26647836SJohn.Forte@Sun.COM 	ret = initializeConfig();
26657836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
26667836SJohn.Forte@Sun.COM 		return (ret);
26677836SJohn.Forte@Sun.COM 	}
26687836SJohn.Forte@Sun.COM 
26697836SJohn.Forte@Sun.COM 	/*
26707836SJohn.Forte@Sun.COM 	 * Open control node for stmf
26717836SJohn.Forte@Sun.COM 	 */
26727836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
26737836SJohn.Forte@Sun.COM 		return (ret);
26747836SJohn.Forte@Sun.COM 
26757836SJohn.Forte@Sun.COM 	/*
26767836SJohn.Forte@Sun.COM 	 * Add the group to the driver
26777836SJohn.Forte@Sun.COM 	 */
26787836SJohn.Forte@Sun.COM 	if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_TARGET_GROUP,
26797836SJohn.Forte@Sun.COM 	    targetGroupName)) != STMF_STATUS_SUCCESS) {
26807836SJohn.Forte@Sun.COM 		goto done;
26817836SJohn.Forte@Sun.COM 	}
26827836SJohn.Forte@Sun.COM 
26839585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
26849585STim.Szeto@Sun.COM 		goto done;
26859585STim.Szeto@Sun.COM 	}
26869585STim.Szeto@Sun.COM 
26877836SJohn.Forte@Sun.COM 	/*
26887836SJohn.Forte@Sun.COM 	 * If the add to the driver was successful, add it to the persistent
26897836SJohn.Forte@Sun.COM 	 * store.
26907836SJohn.Forte@Sun.COM 	 */
26917836SJohn.Forte@Sun.COM 	ret = psCreateTargetGroup((char *)targetGroupName);
26927836SJohn.Forte@Sun.COM 	switch (ret) {
26937836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
26947836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
26957836SJohn.Forte@Sun.COM 			break;
26967836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_EXISTS:
26977836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_EXISTS;
26987836SJohn.Forte@Sun.COM 			break;
26997836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
27007836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
27017836SJohn.Forte@Sun.COM 			break;
27027836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
27037836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
27047836SJohn.Forte@Sun.COM 			break;
27057836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
27067836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
27077836SJohn.Forte@Sun.COM 			break;
27087836SJohn.Forte@Sun.COM 		default:
27097836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
27107836SJohn.Forte@Sun.COM 			    "stmfCreateTargetGroup:psCreateTargetGroup"
27117836SJohn.Forte@Sun.COM 			    ":error(%d)", ret);
27127836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
27137836SJohn.Forte@Sun.COM 			break;
27147836SJohn.Forte@Sun.COM 	}
27157836SJohn.Forte@Sun.COM 
27167836SJohn.Forte@Sun.COM done:
27177836SJohn.Forte@Sun.COM 	(void) close(fd);
27187836SJohn.Forte@Sun.COM 	return (ret);
27197836SJohn.Forte@Sun.COM }
27207836SJohn.Forte@Sun.COM 
27217836SJohn.Forte@Sun.COM /*
27227836SJohn.Forte@Sun.COM  * stmfDeleteHostGroup
27237836SJohn.Forte@Sun.COM  *
27247836SJohn.Forte@Sun.COM  * Purpose: Delete an initiator or local port group
27257836SJohn.Forte@Sun.COM  *
27267836SJohn.Forte@Sun.COM  * hostGroupName - group to delete
27277836SJohn.Forte@Sun.COM  */
27287836SJohn.Forte@Sun.COM int
27297836SJohn.Forte@Sun.COM stmfDeleteHostGroup(stmfGroupName *hostGroupName)
27307836SJohn.Forte@Sun.COM {
27317836SJohn.Forte@Sun.COM 	int ret;
27327836SJohn.Forte@Sun.COM 	int fd;
27337836SJohn.Forte@Sun.COM 
27347836SJohn.Forte@Sun.COM 	if (hostGroupName == NULL) {
27357836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
27367836SJohn.Forte@Sun.COM 	}
27377836SJohn.Forte@Sun.COM 
27387836SJohn.Forte@Sun.COM 	/* Check to ensure service exists */
27397836SJohn.Forte@Sun.COM 	if (psCheckService() != STMF_STATUS_SUCCESS) {
27407836SJohn.Forte@Sun.COM 		return (STMF_ERROR_SERVICE_NOT_FOUND);
27417836SJohn.Forte@Sun.COM 	}
27427836SJohn.Forte@Sun.COM 
27437836SJohn.Forte@Sun.COM 	/* call init */
27447836SJohn.Forte@Sun.COM 	ret = initializeConfig();
27457836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
27467836SJohn.Forte@Sun.COM 		return (ret);
27477836SJohn.Forte@Sun.COM 	}
27487836SJohn.Forte@Sun.COM 
27497836SJohn.Forte@Sun.COM 	/*
27507836SJohn.Forte@Sun.COM 	 * Open control node for stmf
27517836SJohn.Forte@Sun.COM 	 */
27527836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
27537836SJohn.Forte@Sun.COM 		return (ret);
27547836SJohn.Forte@Sun.COM 
27557836SJohn.Forte@Sun.COM 	/*
27567836SJohn.Forte@Sun.COM 	 * Remove the group from the driver
27577836SJohn.Forte@Sun.COM 	 */
27587836SJohn.Forte@Sun.COM 	if ((ret = groupIoctl(fd, STMF_IOCTL_REMOVE_HOST_GROUP,
27597836SJohn.Forte@Sun.COM 	    hostGroupName)) != STMF_STATUS_SUCCESS) {
27607836SJohn.Forte@Sun.COM 		goto done;
27617836SJohn.Forte@Sun.COM 	}
27627836SJohn.Forte@Sun.COM 
27639585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
27649585STim.Szeto@Sun.COM 		goto done;
27659585STim.Szeto@Sun.COM 	}
27669585STim.Szeto@Sun.COM 
27677836SJohn.Forte@Sun.COM 	/*
27687836SJohn.Forte@Sun.COM 	 * If the remove from the driver was successful, remove it from the
27697836SJohn.Forte@Sun.COM 	 * persistent store.
27707836SJohn.Forte@Sun.COM 	 */
27717836SJohn.Forte@Sun.COM 	ret = psDeleteHostGroup((char *)hostGroupName);
27727836SJohn.Forte@Sun.COM 	switch (ret) {
27737836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
27747836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
27757836SJohn.Forte@Sun.COM 			break;
27767836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
27777836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
27787836SJohn.Forte@Sun.COM 			break;
27797836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
27807836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
27817836SJohn.Forte@Sun.COM 			break;
27827836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
27837836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
27847836SJohn.Forte@Sun.COM 			break;
27857836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
27867836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
27877836SJohn.Forte@Sun.COM 			break;
27887836SJohn.Forte@Sun.COM 		default:
27897836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
27907836SJohn.Forte@Sun.COM 			    "stmfDeleteHostGroup:psDeleteHostGroup:error(%d)",
27917836SJohn.Forte@Sun.COM 			    ret);
27927836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
27937836SJohn.Forte@Sun.COM 			break;
27947836SJohn.Forte@Sun.COM 	}
27957836SJohn.Forte@Sun.COM 
27967836SJohn.Forte@Sun.COM done:
27977836SJohn.Forte@Sun.COM 	(void) close(fd);
27987836SJohn.Forte@Sun.COM 	return (ret);
27997836SJohn.Forte@Sun.COM }
28007836SJohn.Forte@Sun.COM 
28017836SJohn.Forte@Sun.COM /*
28027836SJohn.Forte@Sun.COM  * stmfDeleteTargetGroup
28037836SJohn.Forte@Sun.COM  *
28047836SJohn.Forte@Sun.COM  * Purpose: Delete an initiator or local port group
28057836SJohn.Forte@Sun.COM  *
28067836SJohn.Forte@Sun.COM  * targetGroupName - group to delete
28077836SJohn.Forte@Sun.COM  */
28087836SJohn.Forte@Sun.COM int
28097836SJohn.Forte@Sun.COM stmfDeleteTargetGroup(stmfGroupName *targetGroupName)
28107836SJohn.Forte@Sun.COM {
28117836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
28127836SJohn.Forte@Sun.COM 	int fd;
28137836SJohn.Forte@Sun.COM 
28147836SJohn.Forte@Sun.COM 	if (targetGroupName == NULL) {
28157836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
28167836SJohn.Forte@Sun.COM 	}
28177836SJohn.Forte@Sun.COM 
28187836SJohn.Forte@Sun.COM 	/* Check to ensure service exists */
28197836SJohn.Forte@Sun.COM 	if (psCheckService() != STMF_STATUS_SUCCESS) {
28207836SJohn.Forte@Sun.COM 		return (STMF_ERROR_SERVICE_NOT_FOUND);
28217836SJohn.Forte@Sun.COM 	}
28227836SJohn.Forte@Sun.COM 
28237836SJohn.Forte@Sun.COM 	/* call init */
28247836SJohn.Forte@Sun.COM 	ret = initializeConfig();
28257836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
28267836SJohn.Forte@Sun.COM 		return (ret);
28277836SJohn.Forte@Sun.COM 	}
28287836SJohn.Forte@Sun.COM 
28297836SJohn.Forte@Sun.COM 	/*
28307836SJohn.Forte@Sun.COM 	 * Open control node for stmf
28317836SJohn.Forte@Sun.COM 	 */
28327836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
28337836SJohn.Forte@Sun.COM 		return (ret);
28347836SJohn.Forte@Sun.COM 
28357836SJohn.Forte@Sun.COM 	/*
28367836SJohn.Forte@Sun.COM 	 * Remove the group from the driver
28377836SJohn.Forte@Sun.COM 	 */
28387836SJohn.Forte@Sun.COM 	if ((ret = groupIoctl(fd, STMF_IOCTL_REMOVE_TARGET_GROUP,
28397836SJohn.Forte@Sun.COM 	    targetGroupName)) != STMF_STATUS_SUCCESS) {
28407836SJohn.Forte@Sun.COM 		goto done;
28417836SJohn.Forte@Sun.COM 	}
28427836SJohn.Forte@Sun.COM 
28439585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
28449585STim.Szeto@Sun.COM 		goto done;
28459585STim.Szeto@Sun.COM 	}
28469585STim.Szeto@Sun.COM 
28477836SJohn.Forte@Sun.COM 	/*
28487836SJohn.Forte@Sun.COM 	 * If the remove from the driver was successful, remove it from the
28497836SJohn.Forte@Sun.COM 	 * persistent store.
28507836SJohn.Forte@Sun.COM 	 */
28517836SJohn.Forte@Sun.COM 	ret = psDeleteTargetGroup((char *)targetGroupName);
28527836SJohn.Forte@Sun.COM 	switch (ret) {
28537836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
28547836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
28557836SJohn.Forte@Sun.COM 			break;
28567836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
28577836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
28587836SJohn.Forte@Sun.COM 			break;
28597836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
28607836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
28617836SJohn.Forte@Sun.COM 			break;
28627836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
28637836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
28647836SJohn.Forte@Sun.COM 			break;
28657836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
28667836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
28677836SJohn.Forte@Sun.COM 			break;
28687836SJohn.Forte@Sun.COM 		default:
28697836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
28707836SJohn.Forte@Sun.COM 			    "stmfDeleteTargetGroup:psDeleteTargetGroup"
28717836SJohn.Forte@Sun.COM 			    ":error(%d)", ret);
28727836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
28737836SJohn.Forte@Sun.COM 			break;
28747836SJohn.Forte@Sun.COM 	}
28757836SJohn.Forte@Sun.COM 
28767836SJohn.Forte@Sun.COM done:
28777836SJohn.Forte@Sun.COM 	(void) close(fd);
28787836SJohn.Forte@Sun.COM 	return (ret);
28797836SJohn.Forte@Sun.COM }
28807836SJohn.Forte@Sun.COM 
28817836SJohn.Forte@Sun.COM /*
28827836SJohn.Forte@Sun.COM  * stmfDevidFromIscsiName
28837836SJohn.Forte@Sun.COM  *
28847836SJohn.Forte@Sun.COM  * Purpose: convert an iSCSI name to an stmf devid
28857836SJohn.Forte@Sun.COM  *
28867836SJohn.Forte@Sun.COM  * iscsiName - unicode nul terminated utf-8 encoded iSCSI name
28877836SJohn.Forte@Sun.COM  * devid - on success, contains the converted iscsi name
28887836SJohn.Forte@Sun.COM  */
28897836SJohn.Forte@Sun.COM int
28907836SJohn.Forte@Sun.COM stmfDevidFromIscsiName(char *iscsiName, stmfDevid *devid)
28917836SJohn.Forte@Sun.COM {
28927836SJohn.Forte@Sun.COM 	if (devid == NULL || iscsiName == NULL)
28937836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
28947836SJohn.Forte@Sun.COM 
28957836SJohn.Forte@Sun.COM 	bzero(devid, sizeof (stmfDevid));
28967836SJohn.Forte@Sun.COM 
28977836SJohn.Forte@Sun.COM 	/* Validate size of target */
28987836SJohn.Forte@Sun.COM 	if ((devid->identLength = strlen(iscsiName)) > MAX_ISCSI_NAME ||
28997836SJohn.Forte@Sun.COM 	    devid->identLength < strlen(EUI) ||
29007836SJohn.Forte@Sun.COM 	    devid->identLength < strlen(IQN)) {
29017836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
29027836SJohn.Forte@Sun.COM 	}
29037836SJohn.Forte@Sun.COM 
29047836SJohn.Forte@Sun.COM 	if ((strncmp(iscsiName, EUI, strlen(EUI)) != 0) &&
29057836SJohn.Forte@Sun.COM 	    strncmp(iscsiName, IQN, strlen(IQN)) != 0) {
29067836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
29077836SJohn.Forte@Sun.COM 	}
29087836SJohn.Forte@Sun.COM 
29097836SJohn.Forte@Sun.COM 	/* copy UTF-8 bytes to ident */
29107836SJohn.Forte@Sun.COM 	bcopy(iscsiName, devid->ident, devid->identLength);
29117836SJohn.Forte@Sun.COM 
29127836SJohn.Forte@Sun.COM 	return (STMF_STATUS_SUCCESS);
29137836SJohn.Forte@Sun.COM }
29147836SJohn.Forte@Sun.COM 
29157836SJohn.Forte@Sun.COM /*
29167836SJohn.Forte@Sun.COM  * stmfDevidFromWwn
29177836SJohn.Forte@Sun.COM  *
29187836SJohn.Forte@Sun.COM  * Purpose: convert a WWN to an stmf devid
29197836SJohn.Forte@Sun.COM  *
29207836SJohn.Forte@Sun.COM  * wwn - 8-byte wwn identifier
29217836SJohn.Forte@Sun.COM  * devid - on success, contains the converted wwn
29227836SJohn.Forte@Sun.COM  */
29237836SJohn.Forte@Sun.COM int
29247836SJohn.Forte@Sun.COM stmfDevidFromWwn(uchar_t *wwn, stmfDevid *devid)
29257836SJohn.Forte@Sun.COM {
29267836SJohn.Forte@Sun.COM 	if (wwn == NULL || devid == NULL)
29277836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
29287836SJohn.Forte@Sun.COM 
29297836SJohn.Forte@Sun.COM 	bzero(devid, sizeof (stmfDevid));
29307836SJohn.Forte@Sun.COM 
29317836SJohn.Forte@Sun.COM 	/* Copy eui prefix */
29327836SJohn.Forte@Sun.COM 	(void) bcopy(WWN, devid->ident, strlen(WWN));
29337836SJohn.Forte@Sun.COM 
29347836SJohn.Forte@Sun.COM 	/* Convert to ASCII uppercase hexadecimal string */
29357836SJohn.Forte@Sun.COM 	(void) snprintf((char *)&devid->ident[strlen(WWN)],
29367836SJohn.Forte@Sun.COM 	    sizeof (devid->ident), "%02X%02X%02X%02X%02X%02X%02X%02X",
29377836SJohn.Forte@Sun.COM 	    wwn[0], wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]);
29387836SJohn.Forte@Sun.COM 
29397836SJohn.Forte@Sun.COM 	devid->identLength = strlen((char *)devid->ident);
29407836SJohn.Forte@Sun.COM 
29417836SJohn.Forte@Sun.COM 	return (STMF_STATUS_SUCCESS);
29427836SJohn.Forte@Sun.COM }
29437836SJohn.Forte@Sun.COM 
29447836SJohn.Forte@Sun.COM /*
29457836SJohn.Forte@Sun.COM  * stmfFreeMemory
29467836SJohn.Forte@Sun.COM  *
29477836SJohn.Forte@Sun.COM  * Purpose: Free memory allocated by this library
29487836SJohn.Forte@Sun.COM  *
29497836SJohn.Forte@Sun.COM  * memory - previously allocated pointer of memory managed by library
29507836SJohn.Forte@Sun.COM  */
29517836SJohn.Forte@Sun.COM void
29527836SJohn.Forte@Sun.COM stmfFreeMemory(void *memory)
29537836SJohn.Forte@Sun.COM {
29547836SJohn.Forte@Sun.COM 	free(memory);
29557836SJohn.Forte@Sun.COM }
29567836SJohn.Forte@Sun.COM 
29577836SJohn.Forte@Sun.COM /*
29589585STim.Szeto@Sun.COM  * get host group, target group list from stmf
29597836SJohn.Forte@Sun.COM  *
29609585STim.Szeto@Sun.COM  * groupType - HOST_GROUP, TARGET_GROUP
29617836SJohn.Forte@Sun.COM  */
29629585STim.Szeto@Sun.COM static int
29639585STim.Szeto@Sun.COM groupListIoctl(stmfGroupList **groupList, int groupType)
29649585STim.Szeto@Sun.COM {
29659585STim.Szeto@Sun.COM 	int ret;
29669585STim.Szeto@Sun.COM 	int fd;
29679585STim.Szeto@Sun.COM 	int ioctlRet;
29689585STim.Szeto@Sun.COM 	int i;
29699585STim.Szeto@Sun.COM 	int cmd;
29709585STim.Szeto@Sun.COM 	stmf_iocdata_t stmfIoctl;
29719585STim.Szeto@Sun.COM 	/* framework group list */
29729585STim.Szeto@Sun.COM 	stmf_group_name_t *iGroupList = NULL;
29739585STim.Szeto@Sun.COM 	uint32_t groupListSize;
29749585STim.Szeto@Sun.COM 
29759585STim.Szeto@Sun.COM 	if (groupList == NULL) {
29769585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
29779585STim.Szeto@Sun.COM 	}
29789585STim.Szeto@Sun.COM 
29799585STim.Szeto@Sun.COM 	if (groupType == HOST_GROUP) {
29809585STim.Szeto@Sun.COM 		cmd = STMF_IOCTL_GET_HG_LIST;
29819585STim.Szeto@Sun.COM 	} else if (groupType == TARGET_GROUP) {
29829585STim.Szeto@Sun.COM 		cmd = STMF_IOCTL_GET_TG_LIST;
29839585STim.Szeto@Sun.COM 	} else {
29849585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
29859585STim.Szeto@Sun.COM 	}
29869585STim.Szeto@Sun.COM 
29879585STim.Szeto@Sun.COM 	/* call init */
29889585STim.Szeto@Sun.COM 	ret = initializeConfig();
29899585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
29909585STim.Szeto@Sun.COM 		return (ret);
29919585STim.Szeto@Sun.COM 	}
29929585STim.Szeto@Sun.COM 
29939585STim.Szeto@Sun.COM 	/*
29949585STim.Szeto@Sun.COM 	 * Open control node for stmf
29959585STim.Szeto@Sun.COM 	 */
29969585STim.Szeto@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
29979585STim.Szeto@Sun.COM 		return (ret);
29989585STim.Szeto@Sun.COM 
29999585STim.Szeto@Sun.COM 	/*
30009585STim.Szeto@Sun.COM 	 * Allocate ioctl input buffer
30019585STim.Szeto@Sun.COM 	 */
30029585STim.Szeto@Sun.COM 	groupListSize = ALLOC_GROUP;
30039585STim.Szeto@Sun.COM 	groupListSize = groupListSize * (sizeof (stmf_group_name_t));
30049585STim.Szeto@Sun.COM 	iGroupList = (stmf_group_name_t *)calloc(1, groupListSize);
30059585STim.Szeto@Sun.COM 	if (iGroupList == NULL) {
30069585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
30079585STim.Szeto@Sun.COM 		goto done;
30089585STim.Szeto@Sun.COM 	}
30099585STim.Szeto@Sun.COM 
30109585STim.Szeto@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
30119585STim.Szeto@Sun.COM 	/*
30129585STim.Szeto@Sun.COM 	 * Issue ioctl to get the group list
30139585STim.Szeto@Sun.COM 	 */
30149585STim.Szeto@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
30159585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf_size = groupListSize;
30169585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupList;
30179585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
30189585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
30199585STim.Szeto@Sun.COM 		switch (errno) {
30209585STim.Szeto@Sun.COM 			case EBUSY:
30219585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
30229585STim.Szeto@Sun.COM 				break;
30239585STim.Szeto@Sun.COM 			case EPERM:
30249585STim.Szeto@Sun.COM 			case EACCES:
30259585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
30269585STim.Szeto@Sun.COM 				break;
30279585STim.Szeto@Sun.COM 			default:
30289585STim.Szeto@Sun.COM 				syslog(LOG_DEBUG,
30299585STim.Szeto@Sun.COM 				    "groupListIoctl:ioctl errno(%d)",
30309585STim.Szeto@Sun.COM 				    errno);
30319585STim.Szeto@Sun.COM 				ret = STMF_STATUS_ERROR;
30329585STim.Szeto@Sun.COM 				break;
30339585STim.Szeto@Sun.COM 		}
30349585STim.Szeto@Sun.COM 		goto done;
30359585STim.Szeto@Sun.COM 	}
30369585STim.Szeto@Sun.COM 	/*
30379585STim.Szeto@Sun.COM 	 * Check whether input buffer was large enough
30389585STim.Szeto@Sun.COM 	 */
30399585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_GROUP) {
30409585STim.Szeto@Sun.COM 		groupListSize = stmfIoctl.stmf_obuf_max_nentries *
30419585STim.Szeto@Sun.COM 		    sizeof (stmf_group_name_t);
30429585STim.Szeto@Sun.COM 		iGroupList = realloc(iGroupList, groupListSize);
30439585STim.Szeto@Sun.COM 		if (iGroupList == NULL) {
30449585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NOMEM;
30459585STim.Szeto@Sun.COM 			goto done;
30469585STim.Szeto@Sun.COM 		}
30479585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf_size = groupListSize;
30489585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupList;
30499585STim.Szeto@Sun.COM 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
30509585STim.Szeto@Sun.COM 		if (ioctlRet != 0) {
30519585STim.Szeto@Sun.COM 			switch (errno) {
30529585STim.Szeto@Sun.COM 				case EBUSY:
30539585STim.Szeto@Sun.COM 					ret = STMF_ERROR_BUSY;
30549585STim.Szeto@Sun.COM 					break;
30559585STim.Szeto@Sun.COM 				case EPERM:
30569585STim.Szeto@Sun.COM 				case EACCES:
30579585STim.Szeto@Sun.COM 					ret = STMF_ERROR_PERM;
30589585STim.Szeto@Sun.COM 					break;
30599585STim.Szeto@Sun.COM 				default:
30609585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
30619585STim.Szeto@Sun.COM 					    "groupListIoctl:ioctl errno(%d)",
30629585STim.Szeto@Sun.COM 					    errno);
30639585STim.Szeto@Sun.COM 					ret = STMF_STATUS_ERROR;
30649585STim.Szeto@Sun.COM 					break;
30659585STim.Szeto@Sun.COM 			}
30669585STim.Szeto@Sun.COM 			goto done;
30679585STim.Szeto@Sun.COM 		}
30689585STim.Szeto@Sun.COM 	}
30699585STim.Szeto@Sun.COM 
30709585STim.Szeto@Sun.COM 	/* allocate and copy to caller's buffer */
30719585STim.Szeto@Sun.COM 	*groupList = (stmfGroupList *)calloc(1, sizeof (stmfGroupList) *
30729585STim.Szeto@Sun.COM 	    stmfIoctl.stmf_obuf_nentries);
30739585STim.Szeto@Sun.COM 	if (*groupList == NULL) {
30749585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
30759585STim.Szeto@Sun.COM 		goto done;
30769585STim.Szeto@Sun.COM 	}
30779585STim.Szeto@Sun.COM 	(*groupList)->cnt = stmfIoctl.stmf_obuf_nentries;
30789585STim.Szeto@Sun.COM 	for (i = 0; i < stmfIoctl.stmf_obuf_nentries; i++) {
30799585STim.Szeto@Sun.COM 		bcopy(iGroupList->name, (*groupList)->name[i],
30809585STim.Szeto@Sun.COM 		    sizeof (stmfGroupName));
30819585STim.Szeto@Sun.COM 		iGroupList++;
30829585STim.Szeto@Sun.COM 	}
30839585STim.Szeto@Sun.COM 
30849585STim.Szeto@Sun.COM done:
30859585STim.Szeto@Sun.COM 	free(iGroupList);
30869585STim.Szeto@Sun.COM 	(void) close(fd);
30879585STim.Szeto@Sun.COM 	return (ret);
30889585STim.Szeto@Sun.COM }
30899585STim.Szeto@Sun.COM 
30909585STim.Szeto@Sun.COM /*
30919585STim.Szeto@Sun.COM  * get host group members, target group members from stmf
30929585STim.Szeto@Sun.COM  *
30939585STim.Szeto@Sun.COM  * groupProps - allocated on success
30949585STim.Szeto@Sun.COM  *
30959585STim.Szeto@Sun.COM  * groupType - HOST_GROUP, TARGET_GROUP
30969585STim.Szeto@Sun.COM  */
30979585STim.Szeto@Sun.COM static int
30989585STim.Szeto@Sun.COM groupMemberListIoctl(stmfGroupName *groupName, stmfGroupProperties **groupProps,
30999585STim.Szeto@Sun.COM     int groupType)
31007836SJohn.Forte@Sun.COM {
31017836SJohn.Forte@Sun.COM 	int ret;
31029585STim.Szeto@Sun.COM 	int fd;
31039585STim.Szeto@Sun.COM 	int ioctlRet;
31049585STim.Szeto@Sun.COM 	int i;
31059585STim.Szeto@Sun.COM 	int cmd;
31069585STim.Szeto@Sun.COM 	stmf_iocdata_t stmfIoctl;
31079585STim.Szeto@Sun.COM 	/* framework group list */
31089585STim.Szeto@Sun.COM 	stmf_group_name_t iGroupName;
31099585STim.Szeto@Sun.COM 	stmf_ge_ident_t *iGroupMembers;
31109585STim.Szeto@Sun.COM 	uint32_t groupListSize;
31119585STim.Szeto@Sun.COM 
31129585STim.Szeto@Sun.COM 	if (groupName == NULL) {
31139585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
31149585STim.Szeto@Sun.COM 	}
31159585STim.Szeto@Sun.COM 
31169585STim.Szeto@Sun.COM 	if (groupType == HOST_GROUP) {
31179585STim.Szeto@Sun.COM 		cmd = STMF_IOCTL_GET_HG_ENTRIES;
31189585STim.Szeto@Sun.COM 	} else if (groupType == TARGET_GROUP) {
31199585STim.Szeto@Sun.COM 		cmd = STMF_IOCTL_GET_TG_ENTRIES;
31209585STim.Szeto@Sun.COM 	} else {
31217836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
31227836SJohn.Forte@Sun.COM 	}
31237836SJohn.Forte@Sun.COM 
31249585STim.Szeto@Sun.COM 	/* call init */
31259585STim.Szeto@Sun.COM 	ret = initializeConfig();
31269585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
31279585STim.Szeto@Sun.COM 		return (ret);
31289585STim.Szeto@Sun.COM 	}
31299585STim.Szeto@Sun.COM 
31309585STim.Szeto@Sun.COM 	/*
31319585STim.Szeto@Sun.COM 	 * Open control node for stmf
31329585STim.Szeto@Sun.COM 	 */
31339585STim.Szeto@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
31349585STim.Szeto@Sun.COM 		return (ret);
31359585STim.Szeto@Sun.COM 
31369585STim.Szeto@Sun.COM 	bzero(&iGroupName, sizeof (iGroupName));
31379585STim.Szeto@Sun.COM 
31389585STim.Szeto@Sun.COM 	bcopy(groupName, &iGroupName.name, strlen((char *)groupName));
31399585STim.Szeto@Sun.COM 
31409585STim.Szeto@Sun.COM 	iGroupName.name_size = strlen((char *)groupName);
31419585STim.Szeto@Sun.COM 
31429585STim.Szeto@Sun.COM 	/*
31439585STim.Szeto@Sun.COM 	 * Allocate ioctl input buffer
31449585STim.Szeto@Sun.COM 	 */
31459585STim.Szeto@Sun.COM 	groupListSize = ALLOC_GRP_MEMBER;
31469585STim.Szeto@Sun.COM 	groupListSize = groupListSize * (sizeof (stmf_ge_ident_t));
31479585STim.Szeto@Sun.COM 	iGroupMembers = (stmf_ge_ident_t *)calloc(1, groupListSize);
31489585STim.Szeto@Sun.COM 	if (iGroupMembers == NULL) {
31499585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
31509585STim.Szeto@Sun.COM 		goto done;
31519585STim.Szeto@Sun.COM 	}
31529585STim.Szeto@Sun.COM 
31539585STim.Szeto@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
31549585STim.Szeto@Sun.COM 	/*
31559585STim.Szeto@Sun.COM 	 * Issue ioctl to get the group list
31569585STim.Szeto@Sun.COM 	 */
31579585STim.Szeto@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
31589585STim.Szeto@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&iGroupName;
31599585STim.Szeto@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (stmf_group_name_t);
31609585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf_size = groupListSize;
31619585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupMembers;
31629585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
31639585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
31649585STim.Szeto@Sun.COM 		switch (errno) {
31659585STim.Szeto@Sun.COM 			case EBUSY:
31669585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
31679585STim.Szeto@Sun.COM 				break;
31689585STim.Szeto@Sun.COM 			case EPERM:
31699585STim.Szeto@Sun.COM 			case EACCES:
31709585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
31719585STim.Szeto@Sun.COM 				break;
31729585STim.Szeto@Sun.COM 			default:
31739585STim.Szeto@Sun.COM 				syslog(LOG_DEBUG,
31749585STim.Szeto@Sun.COM 				    "groupListIoctl:ioctl errno(%d)",
31759585STim.Szeto@Sun.COM 				    errno);
31769585STim.Szeto@Sun.COM 				ret = STMF_STATUS_ERROR;
31779585STim.Szeto@Sun.COM 				break;
31789585STim.Szeto@Sun.COM 		}
31799585STim.Szeto@Sun.COM 		goto done;
31809585STim.Szeto@Sun.COM 	}
31819585STim.Szeto@Sun.COM 	/*
31829585STim.Szeto@Sun.COM 	 * Check whether input buffer was large enough
31839585STim.Szeto@Sun.COM 	 */
31849585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_GRP_MEMBER) {
31859585STim.Szeto@Sun.COM 		groupListSize = stmfIoctl.stmf_obuf_max_nentries *
31869585STim.Szeto@Sun.COM 		    sizeof (stmf_ge_ident_t);
31879585STim.Szeto@Sun.COM 		iGroupMembers = realloc(iGroupMembers, groupListSize);
31889585STim.Szeto@Sun.COM 		if (iGroupMembers == NULL) {
31899585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NOMEM;
31909585STim.Szeto@Sun.COM 			goto done;
31919585STim.Szeto@Sun.COM 		}
31929585STim.Szeto@Sun.COM 		stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&iGroupName;
31939585STim.Szeto@Sun.COM 		stmfIoctl.stmf_ibuf_size = sizeof (stmf_group_name_t);
31949585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf_size = groupListSize;
31959585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupMembers;
31969585STim.Szeto@Sun.COM 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
31979585STim.Szeto@Sun.COM 		if (ioctlRet != 0) {
31989585STim.Szeto@Sun.COM 			switch (errno) {
31999585STim.Szeto@Sun.COM 				case EBUSY:
32009585STim.Szeto@Sun.COM 					ret = STMF_ERROR_BUSY;
32019585STim.Szeto@Sun.COM 					break;
32029585STim.Szeto@Sun.COM 				case EPERM:
32039585STim.Szeto@Sun.COM 				case EACCES:
32049585STim.Szeto@Sun.COM 					ret = STMF_ERROR_PERM;
32059585STim.Szeto@Sun.COM 					break;
32069585STim.Szeto@Sun.COM 				default:
32079585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
32089585STim.Szeto@Sun.COM 					    "groupListIoctl:ioctl errno(%d)",
32099585STim.Szeto@Sun.COM 					    errno);
32109585STim.Szeto@Sun.COM 					ret = STMF_STATUS_ERROR;
32119585STim.Szeto@Sun.COM 					break;
32129585STim.Szeto@Sun.COM 			}
32139585STim.Szeto@Sun.COM 			goto done;
32149585STim.Szeto@Sun.COM 		}
32159585STim.Szeto@Sun.COM 	}
32169585STim.Szeto@Sun.COM 
32179585STim.Szeto@Sun.COM 	/* allocate and copy to caller's buffer */
32189585STim.Szeto@Sun.COM 	*groupProps = (stmfGroupProperties *)calloc(1,
32199585STim.Szeto@Sun.COM 	    sizeof (stmfGroupProperties) * stmfIoctl.stmf_obuf_nentries);
32209585STim.Szeto@Sun.COM 	if (*groupProps == NULL) {
32219585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
32229585STim.Szeto@Sun.COM 		goto done;
32239585STim.Szeto@Sun.COM 	}
32249585STim.Szeto@Sun.COM 	(*groupProps)->cnt = stmfIoctl.stmf_obuf_nentries;
32259585STim.Szeto@Sun.COM 	for (i = 0; i < stmfIoctl.stmf_obuf_nentries; i++) {
32269585STim.Szeto@Sun.COM 		(*groupProps)->name[i].identLength =
32279585STim.Szeto@Sun.COM 		    iGroupMembers->ident_size;
32289585STim.Szeto@Sun.COM 		bcopy(iGroupMembers->ident, (*groupProps)->name[i].ident,
32299585STim.Szeto@Sun.COM 		    iGroupMembers->ident_size);
32309585STim.Szeto@Sun.COM 		iGroupMembers++;
32319585STim.Szeto@Sun.COM 	}
32329585STim.Szeto@Sun.COM 
32339585STim.Szeto@Sun.COM done:
32349585STim.Szeto@Sun.COM 	free(iGroupMembers);
32359585STim.Szeto@Sun.COM 	(void) close(fd);
32369585STim.Szeto@Sun.COM 	return (ret);
32379585STim.Szeto@Sun.COM }
32389585STim.Szeto@Sun.COM 
32399585STim.Szeto@Sun.COM /*
32409585STim.Szeto@Sun.COM  * Purpose: access persistent config data for host groups and target groups
32419585STim.Szeto@Sun.COM  */
32429585STim.Szeto@Sun.COM static int
32439585STim.Szeto@Sun.COM iLoadGroupFromPs(stmfGroupList **groupList, int type)
32449585STim.Szeto@Sun.COM {
32459585STim.Szeto@Sun.COM 	int ret;
32469585STim.Szeto@Sun.COM 
32479585STim.Szeto@Sun.COM 	if (groupList == NULL) {
32489585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
32499585STim.Szeto@Sun.COM 	}
32509585STim.Szeto@Sun.COM 
32519585STim.Szeto@Sun.COM 	if (type == HOST_GROUP) {
32529585STim.Szeto@Sun.COM 		ret = psGetHostGroupList(groupList);
32539585STim.Szeto@Sun.COM 	} else if (type == TARGET_GROUP) {
32549585STim.Szeto@Sun.COM 		ret = psGetTargetGroupList(groupList);
32559585STim.Szeto@Sun.COM 	} else {
32569585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
32579585STim.Szeto@Sun.COM 	}
32587836SJohn.Forte@Sun.COM 	switch (ret) {
32597836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
32607836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
32617836SJohn.Forte@Sun.COM 			break;
32627836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
32637836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
32647836SJohn.Forte@Sun.COM 			break;
32657836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
32667836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
32677836SJohn.Forte@Sun.COM 			break;
32687836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
32697836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
32707836SJohn.Forte@Sun.COM 			break;
32717836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
32727836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
32737836SJohn.Forte@Sun.COM 			break;
32747836SJohn.Forte@Sun.COM 		default:
32757836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
32767836SJohn.Forte@Sun.COM 			    "stmfGetHostGroupList:psGetHostGroupList:error(%d)",
32777836SJohn.Forte@Sun.COM 			    ret);
32787836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
32797836SJohn.Forte@Sun.COM 			break;
32807836SJohn.Forte@Sun.COM 	}
32817836SJohn.Forte@Sun.COM 
32827836SJohn.Forte@Sun.COM 	return (ret);
32837836SJohn.Forte@Sun.COM }
32847836SJohn.Forte@Sun.COM 
32857836SJohn.Forte@Sun.COM /*
32869585STim.Szeto@Sun.COM  * stmfGetHostGroupList
32877836SJohn.Forte@Sun.COM  *
32889585STim.Szeto@Sun.COM  * Purpose: Retrieves the list of initiator group oids
32899585STim.Szeto@Sun.COM  *
32909585STim.Szeto@Sun.COM  * hostGroupList - pointer to pointer to hostGroupList structure
32919585STim.Szeto@Sun.COM  *                 on success, this contains the host group list.
32927836SJohn.Forte@Sun.COM  */
32937836SJohn.Forte@Sun.COM int
32949585STim.Szeto@Sun.COM stmfGetHostGroupList(stmfGroupList **hostGroupList)
32959585STim.Szeto@Sun.COM {
32969585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_ERROR;
32979585STim.Szeto@Sun.COM 
32989585STim.Szeto@Sun.COM 	if (hostGroupList == NULL) {
32999585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
33009585STim.Szeto@Sun.COM 	}
33019585STim.Szeto@Sun.COM 
33029585STim.Szeto@Sun.COM 	ret = groupListIoctl(hostGroupList, HOST_GROUP);
33039585STim.Szeto@Sun.COM 	return (ret);
33049585STim.Szeto@Sun.COM }
33059585STim.Szeto@Sun.COM 
33069585STim.Szeto@Sun.COM 
33079585STim.Szeto@Sun.COM /*
33089585STim.Szeto@Sun.COM  * Purpose: access persistent config data for host groups and target groups
33099585STim.Szeto@Sun.COM  */
33109585STim.Szeto@Sun.COM static int
33119585STim.Szeto@Sun.COM iLoadGroupMembersFromPs(stmfGroupName *groupName,
33129585STim.Szeto@Sun.COM     stmfGroupProperties **groupProp, int type)
33137836SJohn.Forte@Sun.COM {
33147836SJohn.Forte@Sun.COM 	int ret;
33157836SJohn.Forte@Sun.COM 
33169585STim.Szeto@Sun.COM 	if (groupName == NULL) {
33177836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
33187836SJohn.Forte@Sun.COM 	}
33197836SJohn.Forte@Sun.COM 
33209585STim.Szeto@Sun.COM 	if (type == HOST_GROUP) {
33219585STim.Szeto@Sun.COM 		ret = psGetHostGroupMemberList((char *)groupName, groupProp);
33229585STim.Szeto@Sun.COM 	} else if (type == TARGET_GROUP) {
33239585STim.Szeto@Sun.COM 		ret = psGetTargetGroupMemberList((char *)groupName, groupProp);
33249585STim.Szeto@Sun.COM 	} else {
33259585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
33269585STim.Szeto@Sun.COM 	}
33277836SJohn.Forte@Sun.COM 	switch (ret) {
33287836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
33297836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
33307836SJohn.Forte@Sun.COM 			break;
33317836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
33327836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
33337836SJohn.Forte@Sun.COM 			break;
33347836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
33357836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
33367836SJohn.Forte@Sun.COM 			break;
33377836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
33387836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
33397836SJohn.Forte@Sun.COM 			break;
33407836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
33417836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
33427836SJohn.Forte@Sun.COM 			break;
33437836SJohn.Forte@Sun.COM 		default:
33447836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
33459585STim.Szeto@Sun.COM 			    "iLoadGroupMembersFromPs:psGetHostGroupList:"
33469585STim.Szeto@Sun.COM 			    "error(%d)", ret);
33477836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
33487836SJohn.Forte@Sun.COM 			break;
33497836SJohn.Forte@Sun.COM 	}
33507836SJohn.Forte@Sun.COM 
33517836SJohn.Forte@Sun.COM 	return (ret);
33527836SJohn.Forte@Sun.COM }
33537836SJohn.Forte@Sun.COM 
33547836SJohn.Forte@Sun.COM /*
33559585STim.Szeto@Sun.COM  * stmfGetHostGroupMembers
33569585STim.Szeto@Sun.COM  *
33579585STim.Szeto@Sun.COM  * Purpose: Retrieves the group properties for a host group
33589585STim.Szeto@Sun.COM  *
33599585STim.Szeto@Sun.COM  * groupName - name of group for which to retrieve host group members.
33609585STim.Szeto@Sun.COM  * groupProp - pointer to pointer to stmfGroupProperties structure
33619585STim.Szeto@Sun.COM  *             on success, this contains the list of group members.
33629585STim.Szeto@Sun.COM  */
33639585STim.Szeto@Sun.COM int
33649585STim.Szeto@Sun.COM stmfGetHostGroupMembers(stmfGroupName *groupName,
33659585STim.Szeto@Sun.COM     stmfGroupProperties **groupProp)
33669585STim.Szeto@Sun.COM {
33679585STim.Szeto@Sun.COM 	int ret;
33689585STim.Szeto@Sun.COM 
33699585STim.Szeto@Sun.COM 	if (groupName == NULL || groupProp == NULL) {
33709585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
33719585STim.Szeto@Sun.COM 	}
33729585STim.Szeto@Sun.COM 
33739585STim.Szeto@Sun.COM 	ret = groupMemberListIoctl(groupName, groupProp, HOST_GROUP);
33749585STim.Szeto@Sun.COM 
33759585STim.Szeto@Sun.COM 	return (ret);
33769585STim.Szeto@Sun.COM }
33779585STim.Szeto@Sun.COM 
33789585STim.Szeto@Sun.COM /*
33797836SJohn.Forte@Sun.COM  * stmfGetProviderData
33807836SJohn.Forte@Sun.COM  *
33817836SJohn.Forte@Sun.COM  * Purpose: Get provider data list
33827836SJohn.Forte@Sun.COM  *
33837836SJohn.Forte@Sun.COM  * providerName - name of provider for which to retrieve the data
33847836SJohn.Forte@Sun.COM  * nvl - pointer to nvlist_t pointer which will contain the nvlist data
33857836SJohn.Forte@Sun.COM  *       retrieved.
33867836SJohn.Forte@Sun.COM  * providerType - type of provider for which to retrieve data.
33877836SJohn.Forte@Sun.COM  *		    STMF_LU_PROVIDER_TYPE
33887836SJohn.Forte@Sun.COM  *		    STMF_PORT_PROVIDER_TYPE
33897836SJohn.Forte@Sun.COM  */
33907836SJohn.Forte@Sun.COM int
33917836SJohn.Forte@Sun.COM stmfGetProviderData(char *providerName, nvlist_t **nvl, int providerType)
33927836SJohn.Forte@Sun.COM {
33937836SJohn.Forte@Sun.COM 	return (stmfGetProviderDataProt(providerName, nvl, providerType,
33947836SJohn.Forte@Sun.COM 	    NULL));
33957836SJohn.Forte@Sun.COM }
33967836SJohn.Forte@Sun.COM 
33977836SJohn.Forte@Sun.COM /*
33987836SJohn.Forte@Sun.COM  * stmfGetProviderDataProt
33997836SJohn.Forte@Sun.COM  *
34007836SJohn.Forte@Sun.COM  * Purpose: Get provider data list with token
34017836SJohn.Forte@Sun.COM  *
34027836SJohn.Forte@Sun.COM  * providerName - name of provider for which to retrieve the data
34037836SJohn.Forte@Sun.COM  * nvl - pointer to nvlist_t pointer which will contain the nvlist data
34047836SJohn.Forte@Sun.COM  *       retrieved.
34057836SJohn.Forte@Sun.COM  * providerType - type of provider for which to retrieve data.
34067836SJohn.Forte@Sun.COM  *		    STMF_LU_PROVIDER_TYPE
34077836SJohn.Forte@Sun.COM  *		    STMF_PORT_PROVIDER_TYPE
34087836SJohn.Forte@Sun.COM  * setToken - Returns the stale data token
34097836SJohn.Forte@Sun.COM  */
34107836SJohn.Forte@Sun.COM int
34117836SJohn.Forte@Sun.COM stmfGetProviderDataProt(char *providerName, nvlist_t **nvl, int providerType,
34127836SJohn.Forte@Sun.COM     uint64_t *setToken)
34137836SJohn.Forte@Sun.COM {
34147836SJohn.Forte@Sun.COM 	int ret;
34157836SJohn.Forte@Sun.COM 
34167836SJohn.Forte@Sun.COM 	if (providerName == NULL || nvl == NULL) {
34177836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
34187836SJohn.Forte@Sun.COM 	}
34197836SJohn.Forte@Sun.COM 	if (providerType != STMF_LU_PROVIDER_TYPE &&
34207836SJohn.Forte@Sun.COM 	    providerType != STMF_PORT_PROVIDER_TYPE) {
34217836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
34227836SJohn.Forte@Sun.COM 	}
34237836SJohn.Forte@Sun.COM 	/* call init */
34247836SJohn.Forte@Sun.COM 	ret = initializeConfig();
34257836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
34267836SJohn.Forte@Sun.COM 		return (ret);
34277836SJohn.Forte@Sun.COM 	}
34289585STim.Szeto@Sun.COM 	return (getProviderData(providerName, nvl, providerType, setToken));
34297836SJohn.Forte@Sun.COM }
34307836SJohn.Forte@Sun.COM 
34317836SJohn.Forte@Sun.COM /*
34327836SJohn.Forte@Sun.COM  * stmfGetProviderDataList
34337836SJohn.Forte@Sun.COM  *
34347836SJohn.Forte@Sun.COM  * Purpose: Get the list of providers currently persisting data
34357836SJohn.Forte@Sun.COM  *
34367836SJohn.Forte@Sun.COM  * providerList - pointer to pointer to an stmfProviderList structure allocated
34377836SJohn.Forte@Sun.COM  *                by the caller. Will contain the list of providers on success.
34387836SJohn.Forte@Sun.COM  */
34397836SJohn.Forte@Sun.COM int
34407836SJohn.Forte@Sun.COM stmfGetProviderDataList(stmfProviderList **providerList)
34417836SJohn.Forte@Sun.COM {
34427836SJohn.Forte@Sun.COM 	int ret;
34437836SJohn.Forte@Sun.COM 
34447836SJohn.Forte@Sun.COM 	ret = psGetProviderDataList(providerList);
34457836SJohn.Forte@Sun.COM 	switch (ret) {
34467836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
34477836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
34487836SJohn.Forte@Sun.COM 			break;
34497836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
34507836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
34517836SJohn.Forte@Sun.COM 			break;
34527836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
34537836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
34547836SJohn.Forte@Sun.COM 			break;
34557836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
34567836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
34577836SJohn.Forte@Sun.COM 			break;
34587836SJohn.Forte@Sun.COM 		default:
34597836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
34607836SJohn.Forte@Sun.COM 			    "stmfGetProviderDataList:psGetProviderDataList"
34617836SJohn.Forte@Sun.COM 			    ":error(%d)", ret);
34627836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
34637836SJohn.Forte@Sun.COM 			break;
34647836SJohn.Forte@Sun.COM 	}
34657836SJohn.Forte@Sun.COM 
34667836SJohn.Forte@Sun.COM 	return (ret);
34677836SJohn.Forte@Sun.COM }
34687836SJohn.Forte@Sun.COM 
34697836SJohn.Forte@Sun.COM 
34707836SJohn.Forte@Sun.COM /*
34717836SJohn.Forte@Sun.COM  * stmfGetSessionList
34727836SJohn.Forte@Sun.COM  *
34737836SJohn.Forte@Sun.COM  * Purpose: Retrieves the session list for a target (devid)
34747836SJohn.Forte@Sun.COM  *
34757836SJohn.Forte@Sun.COM  * devid - devid of target for which to retrieve session information.
34767836SJohn.Forte@Sun.COM  * sessionList - pointer to pointer to stmfSessionList structure
34777836SJohn.Forte@Sun.COM  *             on success, this contains the list of initiator sessions.
34787836SJohn.Forte@Sun.COM  */
34797836SJohn.Forte@Sun.COM int
34807836SJohn.Forte@Sun.COM stmfGetSessionList(stmfDevid *devid, stmfSessionList **sessionList)
34817836SJohn.Forte@Sun.COM {
34827836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
34837836SJohn.Forte@Sun.COM 	int fd;
34847836SJohn.Forte@Sun.COM 	int ioctlRet;
34857836SJohn.Forte@Sun.COM 	int cmd = STMF_IOCTL_SESSION_LIST;
34867836SJohn.Forte@Sun.COM 	int i;
34877836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
34887836SJohn.Forte@Sun.COM 	slist_scsi_session_t *fSessionList;
34897836SJohn.Forte@Sun.COM 	uint8_t ident[260];
34907836SJohn.Forte@Sun.COM 	uint32_t fSessionListSize;
34917836SJohn.Forte@Sun.COM 
34927836SJohn.Forte@Sun.COM 	if (sessionList == NULL || devid == NULL) {
34937836SJohn.Forte@Sun.COM 		ret = STMF_ERROR_INVALID_ARG;
34947836SJohn.Forte@Sun.COM 	}
34957836SJohn.Forte@Sun.COM 
34967836SJohn.Forte@Sun.COM 	/* call init */
34977836SJohn.Forte@Sun.COM 	ret = initializeConfig();
34987836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
34997836SJohn.Forte@Sun.COM 		return (ret);
35007836SJohn.Forte@Sun.COM 	}
35017836SJohn.Forte@Sun.COM 
35027836SJohn.Forte@Sun.COM 	/*
35037836SJohn.Forte@Sun.COM 	 * Open control node for stmf
35047836SJohn.Forte@Sun.COM 	 */
35057836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
35067836SJohn.Forte@Sun.COM 		return (ret);
35077836SJohn.Forte@Sun.COM 
35087836SJohn.Forte@Sun.COM 	/*
35097836SJohn.Forte@Sun.COM 	 * Allocate ioctl input buffer
35107836SJohn.Forte@Sun.COM 	 */
35119585STim.Szeto@Sun.COM 	fSessionListSize = ALLOC_SESSION;
35127836SJohn.Forte@Sun.COM 	fSessionListSize = fSessionListSize * (sizeof (slist_scsi_session_t));
35137836SJohn.Forte@Sun.COM 	fSessionList = (slist_scsi_session_t *)calloc(1, fSessionListSize);
35147836SJohn.Forte@Sun.COM 	if (fSessionList == NULL) {
35157836SJohn.Forte@Sun.COM 		return (STMF_ERROR_NOMEM);
35167836SJohn.Forte@Sun.COM 	}
35177836SJohn.Forte@Sun.COM 
35187836SJohn.Forte@Sun.COM 	ident[IDENT_LENGTH_BYTE] = devid->identLength;
35197836SJohn.Forte@Sun.COM 	bcopy(&(devid->ident), &ident[IDENT_LENGTH_BYTE + 1],
35207836SJohn.Forte@Sun.COM 	    devid->identLength);
35217836SJohn.Forte@Sun.COM 
35227836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
35237836SJohn.Forte@Sun.COM 	/*
35247836SJohn.Forte@Sun.COM 	 * Issue ioctl to get the session list
35257836SJohn.Forte@Sun.COM 	 */
35267836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
35277836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ident;
35287836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (ident);
35297836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = fSessionListSize;
35307836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fSessionList;
35317836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
35327836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
35337836SJohn.Forte@Sun.COM 		switch (errno) {
35347836SJohn.Forte@Sun.COM 			case EBUSY:
35357836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
35367836SJohn.Forte@Sun.COM 				break;
35379585STim.Szeto@Sun.COM 			case EPERM:
35387836SJohn.Forte@Sun.COM 			case EACCES:
35397836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
35407836SJohn.Forte@Sun.COM 				break;
35417836SJohn.Forte@Sun.COM 			default:
35427836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
35437836SJohn.Forte@Sun.COM 				    "stmfGetSessionList:ioctl errno(%d)",
35447836SJohn.Forte@Sun.COM 				    errno);
35457836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
35467836SJohn.Forte@Sun.COM 				break;
35477836SJohn.Forte@Sun.COM 		}
35487836SJohn.Forte@Sun.COM 		goto done;
35497836SJohn.Forte@Sun.COM 	}
35507836SJohn.Forte@Sun.COM 	/*
35517836SJohn.Forte@Sun.COM 	 * Check whether input buffer was large enough
35527836SJohn.Forte@Sun.COM 	 */
35539585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_SESSION) {
35547836SJohn.Forte@Sun.COM 		fSessionListSize = stmfIoctl.stmf_obuf_max_nentries *
35557836SJohn.Forte@Sun.COM 		    sizeof (slist_scsi_session_t);
35567836SJohn.Forte@Sun.COM 		fSessionList = realloc(fSessionList, fSessionListSize);
35577836SJohn.Forte@Sun.COM 		if (fSessionList == NULL) {
35587836SJohn.Forte@Sun.COM 			return (STMF_ERROR_NOMEM);
35597836SJohn.Forte@Sun.COM 		}
35607836SJohn.Forte@Sun.COM 		stmfIoctl.stmf_obuf_size = fSessionListSize;
35617836SJohn.Forte@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fSessionList;
35627836SJohn.Forte@Sun.COM 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
35637836SJohn.Forte@Sun.COM 		if (ioctlRet != 0) {
35647836SJohn.Forte@Sun.COM 			switch (errno) {
35657836SJohn.Forte@Sun.COM 				case EBUSY:
35667836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_BUSY;
35677836SJohn.Forte@Sun.COM 					break;
35689585STim.Szeto@Sun.COM 				case EPERM:
35697836SJohn.Forte@Sun.COM 				case EACCES:
35707836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_PERM;
35717836SJohn.Forte@Sun.COM 					break;
35727836SJohn.Forte@Sun.COM 				default:
35737836SJohn.Forte@Sun.COM 					syslog(LOG_DEBUG,
35747836SJohn.Forte@Sun.COM 					    "stmfGetSessionList:ioctl "
35757836SJohn.Forte@Sun.COM 					    "errno(%d)", errno);
35767836SJohn.Forte@Sun.COM 					ret = STMF_STATUS_ERROR;
35777836SJohn.Forte@Sun.COM 					break;
35787836SJohn.Forte@Sun.COM 			}
35797836SJohn.Forte@Sun.COM 			goto done;
35807836SJohn.Forte@Sun.COM 		}
35817836SJohn.Forte@Sun.COM 	}
35827836SJohn.Forte@Sun.COM 
35837836SJohn.Forte@Sun.COM 	/*
35847836SJohn.Forte@Sun.COM 	 * allocate caller's buffer with the final size
35857836SJohn.Forte@Sun.COM 	 */
35867836SJohn.Forte@Sun.COM 	*sessionList = (stmfSessionList *)calloc(1, sizeof (stmfSessionList) +
35877836SJohn.Forte@Sun.COM 	    stmfIoctl.stmf_obuf_max_nentries * sizeof (stmfSession));
35887836SJohn.Forte@Sun.COM 	if (*sessionList == NULL) {
35897836SJohn.Forte@Sun.COM 		ret = STMF_ERROR_NOMEM;
35907836SJohn.Forte@Sun.COM 		free(sessionList);
35917836SJohn.Forte@Sun.COM 		goto done;
35927836SJohn.Forte@Sun.COM 	}
35937836SJohn.Forte@Sun.COM 
35947836SJohn.Forte@Sun.COM 	(*sessionList)->cnt = stmfIoctl.stmf_obuf_max_nentries;
35957836SJohn.Forte@Sun.COM 
35967836SJohn.Forte@Sun.COM 	/*
35977836SJohn.Forte@Sun.COM 	 * copy session info to caller's buffer
35987836SJohn.Forte@Sun.COM 	 */
35997836SJohn.Forte@Sun.COM 	for (i = 0; i < (*sessionList)->cnt; i++) {
36007836SJohn.Forte@Sun.COM 		(*sessionList)->session[i].initiator.identLength =
36017836SJohn.Forte@Sun.COM 		    fSessionList->initiator[IDENT_LENGTH_BYTE];
36027836SJohn.Forte@Sun.COM 		bcopy(&(fSessionList->initiator[IDENT_LENGTH_BYTE + 1]),
36037836SJohn.Forte@Sun.COM 		    (*sessionList)->session[i].initiator.ident,
36047836SJohn.Forte@Sun.COM 		    STMF_IDENT_LENGTH);
36057836SJohn.Forte@Sun.COM 		bcopy(&(fSessionList->alias),
36067836SJohn.Forte@Sun.COM 		    &((*sessionList)->session[i].alias),
36077836SJohn.Forte@Sun.COM 		    sizeof ((*sessionList)->session[i].alias));
36087836SJohn.Forte@Sun.COM 		bcopy(&(fSessionList++->creation_time),
36097836SJohn.Forte@Sun.COM 		    &((*sessionList)->session[i].creationTime),
36107836SJohn.Forte@Sun.COM 		    sizeof (time_t));
36117836SJohn.Forte@Sun.COM 	}
36127836SJohn.Forte@Sun.COM done:
36137836SJohn.Forte@Sun.COM 	(void) close(fd);
36147836SJohn.Forte@Sun.COM 	return (ret);
36157836SJohn.Forte@Sun.COM }
36167836SJohn.Forte@Sun.COM 
36177836SJohn.Forte@Sun.COM /*
36187836SJohn.Forte@Sun.COM  * stmfGetTargetGroupList
36197836SJohn.Forte@Sun.COM  *
36207836SJohn.Forte@Sun.COM  * Purpose: Retrieves the list of target groups
36217836SJohn.Forte@Sun.COM  *
36227836SJohn.Forte@Sun.COM  * targetGroupList - pointer to a pointer to an stmfGroupList structure. On
36237836SJohn.Forte@Sun.COM  *		     success, it contains the list of target groups.
36247836SJohn.Forte@Sun.COM  */
36257836SJohn.Forte@Sun.COM int
36267836SJohn.Forte@Sun.COM stmfGetTargetGroupList(stmfGroupList **targetGroupList)
36277836SJohn.Forte@Sun.COM {
36287836SJohn.Forte@Sun.COM 	int ret;
36297836SJohn.Forte@Sun.COM 
36307836SJohn.Forte@Sun.COM 	if (targetGroupList == NULL) {
36317836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
36327836SJohn.Forte@Sun.COM 	}
36337836SJohn.Forte@Sun.COM 
36349585STim.Szeto@Sun.COM 	ret = groupListIoctl(targetGroupList, TARGET_GROUP);
36357836SJohn.Forte@Sun.COM 	return (ret);
36367836SJohn.Forte@Sun.COM }
36377836SJohn.Forte@Sun.COM 
36387836SJohn.Forte@Sun.COM /*
36397836SJohn.Forte@Sun.COM  * stmfGetTargetGroupMembers
36407836SJohn.Forte@Sun.COM  *
36417836SJohn.Forte@Sun.COM  * Purpose: Retrieves the group members for a target group
36427836SJohn.Forte@Sun.COM  *
36437836SJohn.Forte@Sun.COM  * groupName - name of target group for which to retrieve members.
36447836SJohn.Forte@Sun.COM  * groupProp - pointer to pointer to stmfGroupProperties structure
36457836SJohn.Forte@Sun.COM  *             on success, this contains the list of group members.
36467836SJohn.Forte@Sun.COM  */
36477836SJohn.Forte@Sun.COM int
36487836SJohn.Forte@Sun.COM stmfGetTargetGroupMembers(stmfGroupName *groupName,
36497836SJohn.Forte@Sun.COM     stmfGroupProperties **groupProp)
36507836SJohn.Forte@Sun.COM {
36517836SJohn.Forte@Sun.COM 	int ret;
36527836SJohn.Forte@Sun.COM 
36537836SJohn.Forte@Sun.COM 	if (groupName == NULL || groupProp == NULL) {
36547836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
36557836SJohn.Forte@Sun.COM 	}
36567836SJohn.Forte@Sun.COM 
36579585STim.Szeto@Sun.COM 	ret = groupMemberListIoctl(groupName, groupProp, TARGET_GROUP);
36587836SJohn.Forte@Sun.COM 
36597836SJohn.Forte@Sun.COM 	return (ret);
36607836SJohn.Forte@Sun.COM }
36617836SJohn.Forte@Sun.COM 
36627836SJohn.Forte@Sun.COM /*
36637836SJohn.Forte@Sun.COM  * stmfGetTargetList
36647836SJohn.Forte@Sun.COM  *
36657836SJohn.Forte@Sun.COM  * Purpose: Retrieves the list of target ports
36667836SJohn.Forte@Sun.COM  *
36677836SJohn.Forte@Sun.COM  * targetList - pointer to a pointer to an stmfDevidList structure.
36687836SJohn.Forte@Sun.COM  *		    On success, it contains the list of local ports (target).
36697836SJohn.Forte@Sun.COM  */
36707836SJohn.Forte@Sun.COM int
36717836SJohn.Forte@Sun.COM stmfGetTargetList(stmfDevidList **targetList)
36727836SJohn.Forte@Sun.COM {
36737836SJohn.Forte@Sun.COM 	int ret;
36747836SJohn.Forte@Sun.COM 	int fd;
36757836SJohn.Forte@Sun.COM 	int ioctlRet;
36767836SJohn.Forte@Sun.COM 	int i;
36777836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
36787836SJohn.Forte@Sun.COM 	/* framework target port list */
36799585STim.Szeto@Sun.COM 	slist_target_port_t *fTargetList, *fTargetListP = NULL;
36807836SJohn.Forte@Sun.COM 	uint32_t fTargetListSize;
36817836SJohn.Forte@Sun.COM 
36827836SJohn.Forte@Sun.COM 	if (targetList == NULL) {
36837836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
36847836SJohn.Forte@Sun.COM 	}
36857836SJohn.Forte@Sun.COM 
36867836SJohn.Forte@Sun.COM 	/* call init */
36877836SJohn.Forte@Sun.COM 	ret = initializeConfig();
36887836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
36897836SJohn.Forte@Sun.COM 		return (ret);
36907836SJohn.Forte@Sun.COM 	}
36917836SJohn.Forte@Sun.COM 
36927836SJohn.Forte@Sun.COM 	/*
36937836SJohn.Forte@Sun.COM 	 * Open control node for stmf
36947836SJohn.Forte@Sun.COM 	 */
36957836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
36967836SJohn.Forte@Sun.COM 		return (ret);
36977836SJohn.Forte@Sun.COM 
36987836SJohn.Forte@Sun.COM 	/*
36997836SJohn.Forte@Sun.COM 	 * Allocate ioctl input buffer
37007836SJohn.Forte@Sun.COM 	 */
37019585STim.Szeto@Sun.COM 	fTargetListSize = ALLOC_TARGET_PORT * sizeof (slist_target_port_t);
37028252SJohn.Forte@Sun.COM 	fTargetListP = fTargetList =
37038252SJohn.Forte@Sun.COM 	    (slist_target_port_t *)calloc(1, fTargetListSize);
37047836SJohn.Forte@Sun.COM 	if (fTargetList == NULL) {
37059585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
37067836SJohn.Forte@Sun.COM 		goto done;
37077836SJohn.Forte@Sun.COM 	}
37087836SJohn.Forte@Sun.COM 
37097836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
37107836SJohn.Forte@Sun.COM 	/*
37118252SJohn.Forte@Sun.COM 	 * Issue ioctl to retrieve target list
37127836SJohn.Forte@Sun.COM 	 */
37137836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
37147836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = fTargetListSize;
37157836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fTargetList;
37167836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_TARGET_PORT_LIST, &stmfIoctl);
37177836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
37187836SJohn.Forte@Sun.COM 		switch (errno) {
37197836SJohn.Forte@Sun.COM 			case EBUSY:
37207836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
37217836SJohn.Forte@Sun.COM 				break;
37229585STim.Szeto@Sun.COM 			case EPERM:
37237836SJohn.Forte@Sun.COM 			case EACCES:
37247836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
37257836SJohn.Forte@Sun.COM 				break;
37267836SJohn.Forte@Sun.COM 			default:
37277836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
37287836SJohn.Forte@Sun.COM 				    "stmfGetTargetList:ioctl errno(%d)", errno);
37297836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
37307836SJohn.Forte@Sun.COM 				break;
37317836SJohn.Forte@Sun.COM 		}
37327836SJohn.Forte@Sun.COM 		goto done;
37337836SJohn.Forte@Sun.COM 	}
37347836SJohn.Forte@Sun.COM 	/*
37357836SJohn.Forte@Sun.COM 	 * Check whether input buffer was large enough
37367836SJohn.Forte@Sun.COM 	 */
37379585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_TARGET_PORT) {
37387836SJohn.Forte@Sun.COM 		fTargetListSize = stmfIoctl.stmf_obuf_max_nentries *
37398116SJohn.Forte@Sun.COM 		    sizeof (slist_target_port_t);
37408252SJohn.Forte@Sun.COM 		fTargetListP = fTargetList =
37418252SJohn.Forte@Sun.COM 		    realloc(fTargetList, fTargetListSize);
37427836SJohn.Forte@Sun.COM 		if (fTargetList == NULL) {
37439585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NOMEM;
37449585STim.Szeto@Sun.COM 			goto done;
37457836SJohn.Forte@Sun.COM 		}
37467836SJohn.Forte@Sun.COM 		stmfIoctl.stmf_obuf_size = fTargetListSize;
37477836SJohn.Forte@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fTargetList;
37487836SJohn.Forte@Sun.COM 		ioctlRet = ioctl(fd, STMF_IOCTL_TARGET_PORT_LIST,
37497836SJohn.Forte@Sun.COM 		    &stmfIoctl);
37507836SJohn.Forte@Sun.COM 		if (ioctlRet != 0) {
37517836SJohn.Forte@Sun.COM 			switch (errno) {
37527836SJohn.Forte@Sun.COM 				case EBUSY:
37537836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_BUSY;
37547836SJohn.Forte@Sun.COM 					break;
37559585STim.Szeto@Sun.COM 				case EPERM:
37567836SJohn.Forte@Sun.COM 				case EACCES:
37577836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_PERM;
37587836SJohn.Forte@Sun.COM 					break;
37597836SJohn.Forte@Sun.COM 				default:
37607836SJohn.Forte@Sun.COM 					syslog(LOG_DEBUG,
37617836SJohn.Forte@Sun.COM 					    "stmfGetTargetList:ioctl errno(%d)",
37627836SJohn.Forte@Sun.COM 					    errno);
37637836SJohn.Forte@Sun.COM 					ret = STMF_STATUS_ERROR;
37647836SJohn.Forte@Sun.COM 					break;
37657836SJohn.Forte@Sun.COM 			}
37667836SJohn.Forte@Sun.COM 			goto done;
37677836SJohn.Forte@Sun.COM 		}
37687836SJohn.Forte@Sun.COM 	}
37697836SJohn.Forte@Sun.COM 
37707836SJohn.Forte@Sun.COM 	*targetList = (stmfDevidList *)calloc(1,
37717836SJohn.Forte@Sun.COM 	    stmfIoctl.stmf_obuf_max_nentries * sizeof (stmfDevid) +
37727836SJohn.Forte@Sun.COM 	    sizeof (stmfDevidList));
37739585STim.Szeto@Sun.COM 	if (*targetList == NULL) {
37749585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
37759585STim.Szeto@Sun.COM 		goto done;
37769585STim.Szeto@Sun.COM 	}
37777836SJohn.Forte@Sun.COM 
37787836SJohn.Forte@Sun.COM 	(*targetList)->cnt = stmfIoctl.stmf_obuf_max_nentries;
37797836SJohn.Forte@Sun.COM 	for (i = 0; i < stmfIoctl.stmf_obuf_max_nentries; i++, fTargetList++) {
37807836SJohn.Forte@Sun.COM 		(*targetList)->devid[i].identLength =
37817836SJohn.Forte@Sun.COM 		    fTargetList->target[IDENT_LENGTH_BYTE];
37827836SJohn.Forte@Sun.COM 		bcopy(&fTargetList->target[IDENT_LENGTH_BYTE + 1],
37837836SJohn.Forte@Sun.COM 		    &(*targetList)->devid[i].ident,
37847836SJohn.Forte@Sun.COM 		    fTargetList->target[IDENT_LENGTH_BYTE]);
37857836SJohn.Forte@Sun.COM 	}
37867836SJohn.Forte@Sun.COM 
37877836SJohn.Forte@Sun.COM done:
37887836SJohn.Forte@Sun.COM 	(void) close(fd);
37898252SJohn.Forte@Sun.COM 	free(fTargetListP);
37907836SJohn.Forte@Sun.COM 	return (ret);
37917836SJohn.Forte@Sun.COM }
37927836SJohn.Forte@Sun.COM 
37937836SJohn.Forte@Sun.COM /*
37947836SJohn.Forte@Sun.COM  * stmfGetTargetProperties
37957836SJohn.Forte@Sun.COM  *
37967836SJohn.Forte@Sun.COM  * Purpose:  Retrieves the properties for a logical unit
37977836SJohn.Forte@Sun.COM  *
37987836SJohn.Forte@Sun.COM  * devid - devid of the target for which to retrieve properties
37997836SJohn.Forte@Sun.COM  * targetProps - pointer to an stmfTargetProperties structure.
38007836SJohn.Forte@Sun.COM  *		On success, it contains the target properties for
38017836SJohn.Forte@Sun.COM  *		the specified devid.
38027836SJohn.Forte@Sun.COM  */
38037836SJohn.Forte@Sun.COM int
38047836SJohn.Forte@Sun.COM stmfGetTargetProperties(stmfDevid *devid, stmfTargetProperties *targetProps)
38057836SJohn.Forte@Sun.COM {
38067836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
38077836SJohn.Forte@Sun.COM 	int fd;
38087836SJohn.Forte@Sun.COM 	int ioctlRet;
38097836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
38107836SJohn.Forte@Sun.COM 	sioc_target_port_props_t targetProperties;
38117836SJohn.Forte@Sun.COM 
38127836SJohn.Forte@Sun.COM 	if (devid == NULL || targetProps == NULL) {
38137836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
38147836SJohn.Forte@Sun.COM 	}
38157836SJohn.Forte@Sun.COM 
38167836SJohn.Forte@Sun.COM 	/* call init */
38177836SJohn.Forte@Sun.COM 	ret = initializeConfig();
38187836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
38197836SJohn.Forte@Sun.COM 		return (ret);
38207836SJohn.Forte@Sun.COM 	}
38217836SJohn.Forte@Sun.COM 
38227836SJohn.Forte@Sun.COM 	/*
38237836SJohn.Forte@Sun.COM 	 * Open control node for stmf
38247836SJohn.Forte@Sun.COM 	 */
38257836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
38267836SJohn.Forte@Sun.COM 		return (ret);
38277836SJohn.Forte@Sun.COM 
38287836SJohn.Forte@Sun.COM 	targetProperties.tgt_id[IDENT_LENGTH_BYTE] = devid->identLength;
38297836SJohn.Forte@Sun.COM 	bcopy(&(devid->ident), &targetProperties.tgt_id[IDENT_LENGTH_BYTE + 1],
38307836SJohn.Forte@Sun.COM 	    devid->identLength);
38317836SJohn.Forte@Sun.COM 
38327836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
38337836SJohn.Forte@Sun.COM 	/*
38347836SJohn.Forte@Sun.COM 	 * Issue ioctl to add to the host group
38357836SJohn.Forte@Sun.COM 	 */
38367836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
38377836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (targetProperties.tgt_id);
38387836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&targetProperties.tgt_id;
38397836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&targetProperties;
38407836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = sizeof (targetProperties);
38417836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_GET_TARGET_PORT_PROPERTIES,
38427836SJohn.Forte@Sun.COM 	    &stmfIoctl);
38437836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
38447836SJohn.Forte@Sun.COM 		switch (errno) {
38457836SJohn.Forte@Sun.COM 			case EBUSY:
38467836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
38477836SJohn.Forte@Sun.COM 				break;
38489585STim.Szeto@Sun.COM 			case EPERM:
38497836SJohn.Forte@Sun.COM 			case EACCES:
38507836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
38517836SJohn.Forte@Sun.COM 				break;
38527836SJohn.Forte@Sun.COM 			case ENOENT:
38537836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
38547836SJohn.Forte@Sun.COM 				break;
38557836SJohn.Forte@Sun.COM 			default:
38567836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
38577836SJohn.Forte@Sun.COM 				    "stmfGetTargetProperties:ioctl errno(%d)",
38587836SJohn.Forte@Sun.COM 				    errno);
38597836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
38607836SJohn.Forte@Sun.COM 				break;
38617836SJohn.Forte@Sun.COM 		}
38627836SJohn.Forte@Sun.COM 		goto done;
38637836SJohn.Forte@Sun.COM 	}
38647836SJohn.Forte@Sun.COM 
38657836SJohn.Forte@Sun.COM 	bcopy(targetProperties.tgt_provider_name, targetProps->providerName,
38667836SJohn.Forte@Sun.COM 	    sizeof (targetProperties.tgt_provider_name));
38677836SJohn.Forte@Sun.COM 	if (targetProperties.tgt_state == STMF_STATE_ONLINE) {
38687836SJohn.Forte@Sun.COM 		targetProps->status = STMF_TARGET_PORT_ONLINE;
38697836SJohn.Forte@Sun.COM 	} else if (targetProperties.tgt_state == STMF_STATE_OFFLINE) {
38707836SJohn.Forte@Sun.COM 		targetProps->status = STMF_TARGET_PORT_OFFLINE;
38717836SJohn.Forte@Sun.COM 	} else if (targetProperties.tgt_state == STMF_STATE_ONLINING) {
38727836SJohn.Forte@Sun.COM 		targetProps->status = STMF_TARGET_PORT_ONLINING;
38737836SJohn.Forte@Sun.COM 	} else if (targetProperties.tgt_state == STMF_STATE_OFFLINING) {
38747836SJohn.Forte@Sun.COM 		targetProps->status = STMF_TARGET_PORT_OFFLINING;
38757836SJohn.Forte@Sun.COM 	}
38767836SJohn.Forte@Sun.COM 	bcopy(targetProperties.tgt_alias, targetProps->alias,
38777836SJohn.Forte@Sun.COM 	    sizeof (targetProps->alias));
38787836SJohn.Forte@Sun.COM done:
38797836SJohn.Forte@Sun.COM 	(void) close(fd);
38807836SJohn.Forte@Sun.COM 	return (ret);
38817836SJohn.Forte@Sun.COM }
38827836SJohn.Forte@Sun.COM 
38837836SJohn.Forte@Sun.COM /*
38847836SJohn.Forte@Sun.COM  * stmfGetLogicalUnitList
38857836SJohn.Forte@Sun.COM  *
38867836SJohn.Forte@Sun.COM  * Purpose: Retrieves list of logical unit Object IDs
38877836SJohn.Forte@Sun.COM  *
38887836SJohn.Forte@Sun.COM  * luList - pointer to a pointer to a stmfGuidList structure. On success,
38897836SJohn.Forte@Sun.COM  *          it contains the list of logical unit guids.
38907836SJohn.Forte@Sun.COM  *
38917836SJohn.Forte@Sun.COM  */
38927836SJohn.Forte@Sun.COM int
38937836SJohn.Forte@Sun.COM stmfGetLogicalUnitList(stmfGuidList **luList)
38947836SJohn.Forte@Sun.COM {
38957836SJohn.Forte@Sun.COM 	int ret;
38967836SJohn.Forte@Sun.COM 	int fd;
38977836SJohn.Forte@Sun.COM 	int ioctlRet;
38987836SJohn.Forte@Sun.COM 	int cmd = STMF_IOCTL_LU_LIST;
38999585STim.Szeto@Sun.COM 	int i;
39007836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
39017836SJohn.Forte@Sun.COM 	slist_lu_t *fLuList;
39027836SJohn.Forte@Sun.COM 	uint32_t fLuListSize;
39039585STim.Szeto@Sun.COM 	uint32_t listCnt;
39047836SJohn.Forte@Sun.COM 
39057836SJohn.Forte@Sun.COM 	if (luList == NULL) {
39067836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
39077836SJohn.Forte@Sun.COM 	}
39087836SJohn.Forte@Sun.COM 
39097836SJohn.Forte@Sun.COM 	/* call init */
39107836SJohn.Forte@Sun.COM 	ret = initializeConfig();
39117836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
39127836SJohn.Forte@Sun.COM 		return (ret);
39137836SJohn.Forte@Sun.COM 	}
39147836SJohn.Forte@Sun.COM 
39157836SJohn.Forte@Sun.COM 	/*
39167836SJohn.Forte@Sun.COM 	 * Open control node for stmf
39177836SJohn.Forte@Sun.COM 	 */
39187836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
39197836SJohn.Forte@Sun.COM 		return (ret);
39207836SJohn.Forte@Sun.COM 
39217836SJohn.Forte@Sun.COM 	/*
39227836SJohn.Forte@Sun.COM 	 * Allocate ioctl input buffer
39237836SJohn.Forte@Sun.COM 	 */
39249585STim.Szeto@Sun.COM 	fLuListSize = ALLOC_LU;
39257836SJohn.Forte@Sun.COM 	fLuListSize = fLuListSize * (sizeof (slist_lu_t));
39267836SJohn.Forte@Sun.COM 	fLuList = (slist_lu_t *)calloc(1, fLuListSize);
39277836SJohn.Forte@Sun.COM 	if (fLuList == NULL) {
39289585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
39299585STim.Szeto@Sun.COM 		goto done;
39307836SJohn.Forte@Sun.COM 	}
39317836SJohn.Forte@Sun.COM 
39327836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
39337836SJohn.Forte@Sun.COM 	/*
39347836SJohn.Forte@Sun.COM 	 * Issue ioctl to get the LU list
39357836SJohn.Forte@Sun.COM 	 */
39367836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
39377836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = fLuListSize;
39387836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fLuList;
39397836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
39407836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
39417836SJohn.Forte@Sun.COM 		switch (errno) {
39427836SJohn.Forte@Sun.COM 			case EBUSY:
39437836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
39447836SJohn.Forte@Sun.COM 				break;
39459585STim.Szeto@Sun.COM 			case EPERM:
39467836SJohn.Forte@Sun.COM 			case EACCES:
39477836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
39487836SJohn.Forte@Sun.COM 				break;
39497836SJohn.Forte@Sun.COM 			default:
39507836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
39517836SJohn.Forte@Sun.COM 				    "stmfGetLogicalUnitList:ioctl errno(%d)",
39527836SJohn.Forte@Sun.COM 				    errno);
39537836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
39547836SJohn.Forte@Sun.COM 				break;
39557836SJohn.Forte@Sun.COM 		}
39567836SJohn.Forte@Sun.COM 		goto done;
39577836SJohn.Forte@Sun.COM 	}
39587836SJohn.Forte@Sun.COM 	/*
39597836SJohn.Forte@Sun.COM 	 * Check whether input buffer was large enough
39607836SJohn.Forte@Sun.COM 	 */
39619585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_LU) {
39627836SJohn.Forte@Sun.COM 		fLuListSize = stmfIoctl.stmf_obuf_max_nentries *
39637836SJohn.Forte@Sun.COM 		    sizeof (slist_lu_t);
39649585STim.Szeto@Sun.COM 		free(fLuList);
39659585STim.Szeto@Sun.COM 		fLuList = (slist_lu_t *)calloc(1, fLuListSize);
39667836SJohn.Forte@Sun.COM 		if (fLuList == NULL) {
39679585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NOMEM;
39689585STim.Szeto@Sun.COM 			goto done;
39697836SJohn.Forte@Sun.COM 		}
39707836SJohn.Forte@Sun.COM 		stmfIoctl.stmf_obuf_size = fLuListSize;
39717836SJohn.Forte@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fLuList;
39727836SJohn.Forte@Sun.COM 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
39737836SJohn.Forte@Sun.COM 		if (ioctlRet != 0) {
39747836SJohn.Forte@Sun.COM 			switch (errno) {
39757836SJohn.Forte@Sun.COM 				case EBUSY:
39767836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_BUSY;
39777836SJohn.Forte@Sun.COM 					break;
39789585STim.Szeto@Sun.COM 				case EPERM:
39797836SJohn.Forte@Sun.COM 				case EACCES:
39807836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_PERM;
39817836SJohn.Forte@Sun.COM 					break;
39827836SJohn.Forte@Sun.COM 				default:
39837836SJohn.Forte@Sun.COM 					syslog(LOG_DEBUG,
39847836SJohn.Forte@Sun.COM 					    "stmfGetLogicalUnitList:"
39857836SJohn.Forte@Sun.COM 					    "ioctl errno(%d)", errno);
39867836SJohn.Forte@Sun.COM 					ret = STMF_STATUS_ERROR;
39877836SJohn.Forte@Sun.COM 					break;
39887836SJohn.Forte@Sun.COM 			}
39897836SJohn.Forte@Sun.COM 			goto done;
39907836SJohn.Forte@Sun.COM 		}
39917836SJohn.Forte@Sun.COM 	}
39927836SJohn.Forte@Sun.COM 
39937836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
39947836SJohn.Forte@Sun.COM 		goto done;
39957836SJohn.Forte@Sun.COM 	}
39967836SJohn.Forte@Sun.COM 
39979585STim.Szeto@Sun.COM 	listCnt = stmfIoctl.stmf_obuf_nentries;
39987836SJohn.Forte@Sun.COM 
39997836SJohn.Forte@Sun.COM 	/*
40007836SJohn.Forte@Sun.COM 	 * allocate caller's buffer with the final size
40017836SJohn.Forte@Sun.COM 	 */
40027836SJohn.Forte@Sun.COM 	*luList = (stmfGuidList *)calloc(1, sizeof (stmfGuidList) +
40039585STim.Szeto@Sun.COM 	    listCnt * sizeof (stmfGuid));
40047836SJohn.Forte@Sun.COM 	if (*luList == NULL) {
40057836SJohn.Forte@Sun.COM 		ret = STMF_ERROR_NOMEM;
40067836SJohn.Forte@Sun.COM 		goto done;
40077836SJohn.Forte@Sun.COM 	}
40087836SJohn.Forte@Sun.COM 
40099585STim.Szeto@Sun.COM 	(*luList)->cnt = listCnt;
40109585STim.Szeto@Sun.COM 
40119585STim.Szeto@Sun.COM 	/* copy to caller's buffer */
40129585STim.Szeto@Sun.COM 	for (i = 0; i < listCnt; i++) {
40139585STim.Szeto@Sun.COM 		bcopy(&fLuList[i].lu_guid, (*luList)->guid[i].guid,
40149585STim.Szeto@Sun.COM 		    sizeof (stmfGuid));
40159585STim.Szeto@Sun.COM 	}
40169585STim.Szeto@Sun.COM 
40177836SJohn.Forte@Sun.COM 	/*
40189585STim.Szeto@Sun.COM 	 * sort the list. This gives a consistent view across gets
40197836SJohn.Forte@Sun.COM 	 */
40209585STim.Szeto@Sun.COM 	qsort((void *)&((*luList)->guid[0]), (*luList)->cnt,
40219585STim.Szeto@Sun.COM 	    sizeof (stmfGuid), guidCompare);
40227836SJohn.Forte@Sun.COM 
40237836SJohn.Forte@Sun.COM done:
40247836SJohn.Forte@Sun.COM 	(void) close(fd);
40257836SJohn.Forte@Sun.COM 	/*
40267836SJohn.Forte@Sun.COM 	 * free internal buffers
40277836SJohn.Forte@Sun.COM 	 */
40287836SJohn.Forte@Sun.COM 	free(fLuList);
40297836SJohn.Forte@Sun.COM 	return (ret);
40307836SJohn.Forte@Sun.COM }
40317836SJohn.Forte@Sun.COM 
40327836SJohn.Forte@Sun.COM /*
40337836SJohn.Forte@Sun.COM  * stmfGetLogicalUnitProperties
40347836SJohn.Forte@Sun.COM  *
40357836SJohn.Forte@Sun.COM  * Purpose:  Retrieves the properties for a logical unit
40367836SJohn.Forte@Sun.COM  *
40377836SJohn.Forte@Sun.COM  * lu - guid of the logical unit for which to retrieve properties
40387836SJohn.Forte@Sun.COM  * stmfLuProps - pointer to an stmfLogicalUnitProperties structure. On success,
40397836SJohn.Forte@Sun.COM  *               it contains the logical unit properties for the specified guid.
40407836SJohn.Forte@Sun.COM  */
40417836SJohn.Forte@Sun.COM int
40427836SJohn.Forte@Sun.COM stmfGetLogicalUnitProperties(stmfGuid *lu, stmfLogicalUnitProperties *luProps)
40437836SJohn.Forte@Sun.COM {
40447836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
40457836SJohn.Forte@Sun.COM 	int stmfRet;
40467836SJohn.Forte@Sun.COM 	int fd;
40477836SJohn.Forte@Sun.COM 	int ioctlRet;
40487836SJohn.Forte@Sun.COM 	int cmd = STMF_IOCTL_GET_LU_PROPERTIES;
40497836SJohn.Forte@Sun.COM 	stmfViewEntryList *viewEntryList = NULL;
40507836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
40517836SJohn.Forte@Sun.COM 	sioc_lu_props_t fLuProps;
40527836SJohn.Forte@Sun.COM 
40539585STim.Szeto@Sun.COM 	if (lu == NULL || luProps == NULL) {
40549585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
40557836SJohn.Forte@Sun.COM 	}
40567836SJohn.Forte@Sun.COM 
40577836SJohn.Forte@Sun.COM 	bzero(luProps, sizeof (stmfLogicalUnitProperties));
40587836SJohn.Forte@Sun.COM 
40597836SJohn.Forte@Sun.COM 	/* call init */
40607836SJohn.Forte@Sun.COM 	ret = initializeConfig();
40617836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
40627836SJohn.Forte@Sun.COM 		return (ret);
40637836SJohn.Forte@Sun.COM 	}
40647836SJohn.Forte@Sun.COM 
40657836SJohn.Forte@Sun.COM 	/*
40667836SJohn.Forte@Sun.COM 	 * Open control node for stmf
40677836SJohn.Forte@Sun.COM 	 */
40687836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
40697836SJohn.Forte@Sun.COM 		return (ret);
40707836SJohn.Forte@Sun.COM 
40717836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
40727836SJohn.Forte@Sun.COM 	/*
40737836SJohn.Forte@Sun.COM 	 * Issue ioctl to add to the host group
40747836SJohn.Forte@Sun.COM 	 */
40757836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
40767836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (stmfGuid);
40777836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)lu;
40787836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&fLuProps;
40797836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = sizeof (fLuProps);
40807836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
40817836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
40827836SJohn.Forte@Sun.COM 		switch (errno) {
40837836SJohn.Forte@Sun.COM 			case EBUSY:
40847836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
40857836SJohn.Forte@Sun.COM 				break;
40869585STim.Szeto@Sun.COM 			case EPERM:
40877836SJohn.Forte@Sun.COM 			case EACCES:
40887836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
40897836SJohn.Forte@Sun.COM 				break;
40907836SJohn.Forte@Sun.COM 			case ENOENT:
40917836SJohn.Forte@Sun.COM 				stmfRet = stmfGetViewEntryList(lu,
40927836SJohn.Forte@Sun.COM 				    &viewEntryList);
40937836SJohn.Forte@Sun.COM 				if (stmfRet == STMF_STATUS_SUCCESS) {
40947836SJohn.Forte@Sun.COM 					luProps->status =
40957836SJohn.Forte@Sun.COM 					    STMF_LOGICAL_UNIT_UNREGISTERED;
40967836SJohn.Forte@Sun.COM 					if (viewEntryList->cnt > 0) {
40977836SJohn.Forte@Sun.COM 						ret = STMF_STATUS_SUCCESS;
40987836SJohn.Forte@Sun.COM 					} else {
40997836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_NOT_FOUND;
41007836SJohn.Forte@Sun.COM 					}
41017836SJohn.Forte@Sun.COM 				} else {
41027836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_NOT_FOUND;
41037836SJohn.Forte@Sun.COM 				}
41047836SJohn.Forte@Sun.COM 				stmfFreeMemory(viewEntryList);
41057836SJohn.Forte@Sun.COM 				break;
41067836SJohn.Forte@Sun.COM 			default:
41077836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
41087836SJohn.Forte@Sun.COM 				    "stmfGetLogicalUnit:ioctl errno(%d)",
41097836SJohn.Forte@Sun.COM 				    errno);
41107836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
41117836SJohn.Forte@Sun.COM 				break;
41127836SJohn.Forte@Sun.COM 		}
41137836SJohn.Forte@Sun.COM 		goto done;
41147836SJohn.Forte@Sun.COM 	}
41157836SJohn.Forte@Sun.COM 
41167836SJohn.Forte@Sun.COM 	bcopy(fLuProps.lu_provider_name, luProps->providerName,
41177836SJohn.Forte@Sun.COM 	    sizeof (fLuProps.lu_provider_name));
41187836SJohn.Forte@Sun.COM 	if (fLuProps.lu_state == STMF_STATE_ONLINE) {
41197836SJohn.Forte@Sun.COM 		luProps->status = STMF_LOGICAL_UNIT_ONLINE;
41207836SJohn.Forte@Sun.COM 	} else if (fLuProps.lu_state == STMF_STATE_OFFLINE) {
41217836SJohn.Forte@Sun.COM 		luProps->status = STMF_LOGICAL_UNIT_OFFLINE;
41227836SJohn.Forte@Sun.COM 	} else if (fLuProps.lu_state == STMF_STATE_ONLINING) {
41237836SJohn.Forte@Sun.COM 		luProps->status = STMF_LOGICAL_UNIT_ONLINING;
41247836SJohn.Forte@Sun.COM 	} else if (fLuProps.lu_state == STMF_STATE_OFFLINING) {
41257836SJohn.Forte@Sun.COM 		luProps->status = STMF_LOGICAL_UNIT_OFFLINING;
41267836SJohn.Forte@Sun.COM 	}
41277836SJohn.Forte@Sun.COM 	bcopy(fLuProps.lu_alias, luProps->alias, sizeof (luProps->alias));
41287836SJohn.Forte@Sun.COM done:
41297836SJohn.Forte@Sun.COM 	(void) close(fd);
41307836SJohn.Forte@Sun.COM 	return (ret);
41317836SJohn.Forte@Sun.COM }
41327836SJohn.Forte@Sun.COM 
41337836SJohn.Forte@Sun.COM /*
41347836SJohn.Forte@Sun.COM  * stmfGetState
41357836SJohn.Forte@Sun.COM  *
41367836SJohn.Forte@Sun.COM  * Purpose: retrieve the current state of the stmf module
41377836SJohn.Forte@Sun.COM  *
41387836SJohn.Forte@Sun.COM  * state - pointer to stmfState structure allocated by the caller
41397836SJohn.Forte@Sun.COM  *         On success, contains the state of stmf
41407836SJohn.Forte@Sun.COM  */
41417836SJohn.Forte@Sun.COM int
41427836SJohn.Forte@Sun.COM stmfGetState(stmfState *state)
41437836SJohn.Forte@Sun.COM {
41447836SJohn.Forte@Sun.COM 	int ret;
41457836SJohn.Forte@Sun.COM 	stmf_state_desc_t iState;
41467836SJohn.Forte@Sun.COM 
41477836SJohn.Forte@Sun.COM 	if (state == NULL) {
41487836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
41497836SJohn.Forte@Sun.COM 	}
41507836SJohn.Forte@Sun.COM 
41517836SJohn.Forte@Sun.COM 	ret = getStmfState(&iState);
41527836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
41537836SJohn.Forte@Sun.COM 		return (ret);
41547836SJohn.Forte@Sun.COM 	}
41557836SJohn.Forte@Sun.COM 	switch (iState.state) {
41567836SJohn.Forte@Sun.COM 		case STMF_STATE_ONLINE:
41577836SJohn.Forte@Sun.COM 			state->operationalState =
41587836SJohn.Forte@Sun.COM 			    STMF_SERVICE_STATE_ONLINE;
41597836SJohn.Forte@Sun.COM 			break;
41607836SJohn.Forte@Sun.COM 		case STMF_STATE_OFFLINE:
41617836SJohn.Forte@Sun.COM 			state->operationalState =
41627836SJohn.Forte@Sun.COM 			    STMF_SERVICE_STATE_OFFLINE;
41637836SJohn.Forte@Sun.COM 			break;
41647836SJohn.Forte@Sun.COM 		case STMF_STATE_ONLINING:
41657836SJohn.Forte@Sun.COM 			state->operationalState =
41667836SJohn.Forte@Sun.COM 			    STMF_SERVICE_STATE_ONLINING;
41677836SJohn.Forte@Sun.COM 			break;
41687836SJohn.Forte@Sun.COM 		case STMF_STATE_OFFLINING:
41697836SJohn.Forte@Sun.COM 			state->operationalState =
41707836SJohn.Forte@Sun.COM 			    STMF_SERVICE_STATE_OFFLINING;
41717836SJohn.Forte@Sun.COM 			break;
41727836SJohn.Forte@Sun.COM 		default:
41737836SJohn.Forte@Sun.COM 			state->operationalState =
41747836SJohn.Forte@Sun.COM 			    STMF_SERVICE_STATE_UNKNOWN;
41757836SJohn.Forte@Sun.COM 			break;
41767836SJohn.Forte@Sun.COM 	}
41777836SJohn.Forte@Sun.COM 	switch (iState.config_state) {
41787836SJohn.Forte@Sun.COM 		case STMF_CONFIG_NONE:
41797836SJohn.Forte@Sun.COM 			state->configState = STMF_CONFIG_STATE_NONE;
41807836SJohn.Forte@Sun.COM 			break;
41817836SJohn.Forte@Sun.COM 		case STMF_CONFIG_INIT:
41827836SJohn.Forte@Sun.COM 			state->configState = STMF_CONFIG_STATE_INIT;
41837836SJohn.Forte@Sun.COM 			break;
41847836SJohn.Forte@Sun.COM 		case STMF_CONFIG_INIT_DONE:
41857836SJohn.Forte@Sun.COM 			state->configState =
41867836SJohn.Forte@Sun.COM 			    STMF_CONFIG_STATE_INIT_DONE;
41877836SJohn.Forte@Sun.COM 			break;
41887836SJohn.Forte@Sun.COM 		default:
41897836SJohn.Forte@Sun.COM 			state->configState =
41907836SJohn.Forte@Sun.COM 			    STMF_CONFIG_STATE_UNKNOWN;
41917836SJohn.Forte@Sun.COM 			break;
41927836SJohn.Forte@Sun.COM 	}
41937836SJohn.Forte@Sun.COM 	return (STMF_STATUS_SUCCESS);
41947836SJohn.Forte@Sun.COM }
41957836SJohn.Forte@Sun.COM 
41967836SJohn.Forte@Sun.COM /*
41977836SJohn.Forte@Sun.COM  * stmfGetViewEntryList
41987836SJohn.Forte@Sun.COM  *
41997836SJohn.Forte@Sun.COM  * Purpose: Retrieves the list of view entries for the specified
42007836SJohn.Forte@Sun.COM  *          logical unit.
42017836SJohn.Forte@Sun.COM  *
42027836SJohn.Forte@Sun.COM  * lu - the guid of the logical unit for which to retrieve the view entry list
42037836SJohn.Forte@Sun.COM  * viewEntryList - a pointer to a pointer to a stmfViewEntryList structure. On
42047836SJohn.Forte@Sun.COM  *                 success, contains the list of view entries.
42057836SJohn.Forte@Sun.COM  */
42067836SJohn.Forte@Sun.COM int
42077836SJohn.Forte@Sun.COM stmfGetViewEntryList(stmfGuid *lu, stmfViewEntryList **viewEntryList)
42087836SJohn.Forte@Sun.COM {
42097836SJohn.Forte@Sun.COM 	int ret;
42109585STim.Szeto@Sun.COM 	int fd;
42119585STim.Szeto@Sun.COM 	int ioctlRet;
42129585STim.Szeto@Sun.COM 	int cmd = STMF_IOCTL_LU_VE_LIST;
42139585STim.Szeto@Sun.COM 	int i;
42149585STim.Szeto@Sun.COM 	stmf_iocdata_t stmfIoctl;
42159585STim.Szeto@Sun.COM 	stmf_view_op_entry_t *fVeList;
42169585STim.Szeto@Sun.COM 	uint32_t fVeListSize;
42179585STim.Szeto@Sun.COM 	uint32_t listCnt;
42187836SJohn.Forte@Sun.COM 
42197836SJohn.Forte@Sun.COM 	if (lu == NULL || viewEntryList == NULL) {
42207836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
42217836SJohn.Forte@Sun.COM 	}
42227836SJohn.Forte@Sun.COM 
42239585STim.Szeto@Sun.COM 	/* call init */
42249585STim.Szeto@Sun.COM 	ret = initializeConfig();
42259585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
42269585STim.Szeto@Sun.COM 		return (ret);
42279585STim.Szeto@Sun.COM 	}
42289585STim.Szeto@Sun.COM 
42299585STim.Szeto@Sun.COM 	/*
42309585STim.Szeto@Sun.COM 	 * Open control node for stmf
42319585STim.Szeto@Sun.COM 	 */
42329585STim.Szeto@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
42339585STim.Szeto@Sun.COM 		return (ret);
42349585STim.Szeto@Sun.COM 
42359585STim.Szeto@Sun.COM 	/*
42369585STim.Szeto@Sun.COM 	 * Allocate ioctl input buffer
42379585STim.Szeto@Sun.COM 	 */
42389585STim.Szeto@Sun.COM 	fVeListSize = ALLOC_VE;
42399585STim.Szeto@Sun.COM 	fVeListSize = fVeListSize * (sizeof (stmf_view_op_entry_t));
42409585STim.Szeto@Sun.COM 	fVeList = (stmf_view_op_entry_t *)calloc(1, fVeListSize);
42419585STim.Szeto@Sun.COM 	if (fVeList == NULL) {
42429585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
42439585STim.Szeto@Sun.COM 		goto done;
42449585STim.Szeto@Sun.COM 	}
42459585STim.Szeto@Sun.COM 
42469585STim.Szeto@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
42479585STim.Szeto@Sun.COM 	/*
42489585STim.Szeto@Sun.COM 	 * Issue ioctl to get the LU list
42499585STim.Szeto@Sun.COM 	 */
42509585STim.Szeto@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
42519585STim.Szeto@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)lu;
42529585STim.Szeto@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (stmfGuid);
42539585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf_size = fVeListSize;
42549585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fVeList;
42559585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
42569585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
42579585STim.Szeto@Sun.COM 		switch (errno) {
42589585STim.Szeto@Sun.COM 			case EBUSY:
42599585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
42609585STim.Szeto@Sun.COM 				break;
42619585STim.Szeto@Sun.COM 			case EPERM:
42629585STim.Szeto@Sun.COM 			case EACCES:
42639585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
42649585STim.Szeto@Sun.COM 				break;
42659585STim.Szeto@Sun.COM 			default:
42669585STim.Szeto@Sun.COM 				syslog(LOG_DEBUG,
42679585STim.Szeto@Sun.COM 				    "stmfGetViewEntryList:ioctl errno(%d)",
42689585STim.Szeto@Sun.COM 				    errno);
42699585STim.Szeto@Sun.COM 				ret = STMF_STATUS_ERROR;
42709585STim.Szeto@Sun.COM 				break;
42719585STim.Szeto@Sun.COM 		}
42729585STim.Szeto@Sun.COM 		goto done;
42739585STim.Szeto@Sun.COM 	}
42749585STim.Szeto@Sun.COM 	/*
42759585STim.Szeto@Sun.COM 	 * Check whether input buffer was large enough
42769585STim.Szeto@Sun.COM 	 */
42779585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_VE) {
42789585STim.Szeto@Sun.COM 		bzero(&stmfIoctl, sizeof (stmfIoctl));
42799585STim.Szeto@Sun.COM 		fVeListSize = stmfIoctl.stmf_obuf_max_nentries *
42809585STim.Szeto@Sun.COM 		    sizeof (stmf_view_op_entry_t);
42819585STim.Szeto@Sun.COM 		free(fVeList);
42829585STim.Szeto@Sun.COM 		fVeList = (stmf_view_op_entry_t *)calloc(1, fVeListSize);
42839585STim.Szeto@Sun.COM 		if (fVeList == NULL) {
42849585STim.Szeto@Sun.COM 			return (STMF_ERROR_NOMEM);
42859585STim.Szeto@Sun.COM 		}
42869585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf_size = fVeListSize;
42879585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fVeList;
42889585STim.Szeto@Sun.COM 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
42899585STim.Szeto@Sun.COM 		if (ioctlRet != 0) {
42909585STim.Szeto@Sun.COM 			switch (errno) {
42919585STim.Szeto@Sun.COM 				case EBUSY:
42929585STim.Szeto@Sun.COM 					ret = STMF_ERROR_BUSY;
42939585STim.Szeto@Sun.COM 					break;
42949585STim.Szeto@Sun.COM 				case EPERM:
42959585STim.Szeto@Sun.COM 				case EACCES:
42969585STim.Szeto@Sun.COM 					ret = STMF_ERROR_PERM;
42979585STim.Szeto@Sun.COM 					break;
42989585STim.Szeto@Sun.COM 				default:
42999585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
43009585STim.Szeto@Sun.COM 					    "stmfGetLogicalUnitList:"
43019585STim.Szeto@Sun.COM 					    "ioctl errno(%d)", errno);
43029585STim.Szeto@Sun.COM 					ret = STMF_STATUS_ERROR;
43039585STim.Szeto@Sun.COM 					break;
43049585STim.Szeto@Sun.COM 			}
43059585STim.Szeto@Sun.COM 			goto done;
43069585STim.Szeto@Sun.COM 		}
43079585STim.Szeto@Sun.COM 	}
43089585STim.Szeto@Sun.COM 
43099585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
43109585STim.Szeto@Sun.COM 		goto done;
43119585STim.Szeto@Sun.COM 	}
43129585STim.Szeto@Sun.COM 
43139585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_nentries == 0) {
43149585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOT_FOUND;
43159585STim.Szeto@Sun.COM 		goto done;
43169585STim.Szeto@Sun.COM 	}
43179585STim.Szeto@Sun.COM 
43189585STim.Szeto@Sun.COM 	listCnt = stmfIoctl.stmf_obuf_nentries;
43199585STim.Szeto@Sun.COM 
43209585STim.Szeto@Sun.COM 	/*
43219585STim.Szeto@Sun.COM 	 * allocate caller's buffer with the final size
43229585STim.Szeto@Sun.COM 	 */
43239585STim.Szeto@Sun.COM 	*viewEntryList = (stmfViewEntryList *)calloc(1,
43249585STim.Szeto@Sun.COM 	    sizeof (stmfViewEntryList) + listCnt * sizeof (stmfViewEntry));
43259585STim.Szeto@Sun.COM 	if (*viewEntryList == NULL) {
43269585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
43279585STim.Szeto@Sun.COM 		goto done;
43289585STim.Szeto@Sun.COM 	}
43299585STim.Szeto@Sun.COM 
43309585STim.Szeto@Sun.COM 	(*viewEntryList)->cnt = listCnt;
43319585STim.Szeto@Sun.COM 
43329585STim.Szeto@Sun.COM 	/* copy to caller's buffer */
43339585STim.Szeto@Sun.COM 	for (i = 0; i < listCnt; i++) {
43349585STim.Szeto@Sun.COM 		(*viewEntryList)->ve[i].veIndexValid = B_TRUE;
43359585STim.Szeto@Sun.COM 		(*viewEntryList)->ve[i].veIndex = fVeList[i].ve_ndx;
43369585STim.Szeto@Sun.COM 		if (fVeList[i].ve_all_hosts == 1) {
43379585STim.Szeto@Sun.COM 			(*viewEntryList)->ve[i].allHosts = B_TRUE;
43389585STim.Szeto@Sun.COM 		} else {
43399585STim.Szeto@Sun.COM 			bcopy(fVeList[i].ve_host_group.name,
43409585STim.Szeto@Sun.COM 			    (*viewEntryList)->ve[i].hostGroup,
43419585STim.Szeto@Sun.COM 			    fVeList[i].ve_host_group.name_size);
43429585STim.Szeto@Sun.COM 		}
43439585STim.Szeto@Sun.COM 		if (fVeList[i].ve_all_targets == 1) {
43449585STim.Szeto@Sun.COM 			(*viewEntryList)->ve[i].allTargets = B_TRUE;
43459585STim.Szeto@Sun.COM 		} else {
43469585STim.Szeto@Sun.COM 			bcopy(fVeList[i].ve_target_group.name,
43479585STim.Szeto@Sun.COM 			    (*viewEntryList)->ve[i].targetGroup,
43489585STim.Szeto@Sun.COM 			    fVeList[i].ve_target_group.name_size);
43499585STim.Szeto@Sun.COM 		}
43509585STim.Szeto@Sun.COM 		bcopy(fVeList[i].ve_lu_nbr, (*viewEntryList)->ve[i].luNbr,
43519585STim.Szeto@Sun.COM 		    sizeof ((*viewEntryList)->ve[i].luNbr));
43529585STim.Szeto@Sun.COM 		(*viewEntryList)->ve[i].luNbrValid = B_TRUE;
43539585STim.Szeto@Sun.COM 	}
43549585STim.Szeto@Sun.COM 
43559585STim.Szeto@Sun.COM 	/*
43569585STim.Szeto@Sun.COM 	 * sort the list. This gives a consistent view across gets
43579585STim.Szeto@Sun.COM 	 */
43589585STim.Szeto@Sun.COM 	qsort((void *)&((*viewEntryList)->ve[0]), (*viewEntryList)->cnt,
43599585STim.Szeto@Sun.COM 	    sizeof (stmfViewEntry), viewEntryCompare);
43609585STim.Szeto@Sun.COM 
43619585STim.Szeto@Sun.COM done:
43629585STim.Szeto@Sun.COM 	(void) close(fd);
43639585STim.Szeto@Sun.COM 	/*
43649585STim.Szeto@Sun.COM 	 * free internal buffers
43659585STim.Szeto@Sun.COM 	 */
43669585STim.Szeto@Sun.COM 	free(fVeList);
43677836SJohn.Forte@Sun.COM 	return (ret);
43687836SJohn.Forte@Sun.COM }
43697836SJohn.Forte@Sun.COM 
43709585STim.Szeto@Sun.COM 
43717836SJohn.Forte@Sun.COM /*
43727836SJohn.Forte@Sun.COM  * loadHostGroups
43737836SJohn.Forte@Sun.COM  *
43747836SJohn.Forte@Sun.COM  * Purpose - issues the ioctl to load the host groups into stmf
43757836SJohn.Forte@Sun.COM  *
43767836SJohn.Forte@Sun.COM  * fd - file descriptor for the control node of stmf.
43777836SJohn.Forte@Sun.COM  * groupList - populated host group list
43787836SJohn.Forte@Sun.COM  */
43797836SJohn.Forte@Sun.COM static int
43807836SJohn.Forte@Sun.COM loadHostGroups(int fd, stmfGroupList *groupList)
43817836SJohn.Forte@Sun.COM {
43827836SJohn.Forte@Sun.COM 	int i, j;
43837836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
43847836SJohn.Forte@Sun.COM 	stmfGroupProperties *groupProps = NULL;
43857836SJohn.Forte@Sun.COM 
43867836SJohn.Forte@Sun.COM 	for (i = 0; i < groupList->cnt; i++) {
43877836SJohn.Forte@Sun.COM 		if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_HOST_GROUP,
43887836SJohn.Forte@Sun.COM 		    &(groupList->name[i]))) != STMF_STATUS_SUCCESS) {
43897836SJohn.Forte@Sun.COM 			goto out;
43907836SJohn.Forte@Sun.COM 		}
43919585STim.Szeto@Sun.COM 		ret = iLoadGroupMembersFromPs(&(groupList->name[i]),
43929585STim.Szeto@Sun.COM 		    &groupProps, HOST_GROUP);
43937836SJohn.Forte@Sun.COM 		for (j = 0; j < groupProps->cnt; j++) {
43947836SJohn.Forte@Sun.COM 			if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_HG_ENTRY,
43957836SJohn.Forte@Sun.COM 			    &(groupList->name[i]), &(groupProps->name[j])))
43967836SJohn.Forte@Sun.COM 			    != STMF_STATUS_SUCCESS) {
43977836SJohn.Forte@Sun.COM 				goto out;
43987836SJohn.Forte@Sun.COM 			}
43997836SJohn.Forte@Sun.COM 		}
44007836SJohn.Forte@Sun.COM 	}
44017836SJohn.Forte@Sun.COM 
44027836SJohn.Forte@Sun.COM 
44037836SJohn.Forte@Sun.COM out:
44047836SJohn.Forte@Sun.COM 	stmfFreeMemory(groupProps);
44057836SJohn.Forte@Sun.COM 	return (ret);
44067836SJohn.Forte@Sun.COM }
44077836SJohn.Forte@Sun.COM 
44087836SJohn.Forte@Sun.COM /*
44097836SJohn.Forte@Sun.COM  * loadTargetGroups
44107836SJohn.Forte@Sun.COM  *
44117836SJohn.Forte@Sun.COM  * Purpose - issues the ioctl to load the target groups into stmf
44127836SJohn.Forte@Sun.COM  *
44137836SJohn.Forte@Sun.COM  * fd - file descriptor for the control node of stmf.
44147836SJohn.Forte@Sun.COM  * groupList - populated target group list.
44157836SJohn.Forte@Sun.COM  */
44167836SJohn.Forte@Sun.COM static int
44177836SJohn.Forte@Sun.COM loadTargetGroups(int fd, stmfGroupList *groupList)
44187836SJohn.Forte@Sun.COM {
44197836SJohn.Forte@Sun.COM 	int i, j;
44207836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
44217836SJohn.Forte@Sun.COM 	stmfGroupProperties *groupProps = NULL;
44227836SJohn.Forte@Sun.COM 
44237836SJohn.Forte@Sun.COM 	for (i = 0; i < groupList->cnt; i++) {
44247836SJohn.Forte@Sun.COM 		if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_TARGET_GROUP,
44257836SJohn.Forte@Sun.COM 		    &(groupList->name[i]))) != STMF_STATUS_SUCCESS) {
44267836SJohn.Forte@Sun.COM 			goto out;
44277836SJohn.Forte@Sun.COM 		}
44289585STim.Szeto@Sun.COM 		ret = iLoadGroupMembersFromPs(&(groupList->name[i]),
44299585STim.Szeto@Sun.COM 		    &groupProps, TARGET_GROUP);
44307836SJohn.Forte@Sun.COM 		for (j = 0; j < groupProps->cnt; j++) {
44317836SJohn.Forte@Sun.COM 			if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_TG_ENTRY,
44327836SJohn.Forte@Sun.COM 			    &(groupList->name[i]), &(groupProps->name[j])))
44337836SJohn.Forte@Sun.COM 			    != STMF_STATUS_SUCCESS) {
44347836SJohn.Forte@Sun.COM 				goto out;
44357836SJohn.Forte@Sun.COM 			}
44367836SJohn.Forte@Sun.COM 		}
44377836SJohn.Forte@Sun.COM 	}
44387836SJohn.Forte@Sun.COM 
44397836SJohn.Forte@Sun.COM 
44407836SJohn.Forte@Sun.COM out:
44417836SJohn.Forte@Sun.COM 	stmfFreeMemory(groupProps);
44427836SJohn.Forte@Sun.COM 	return (ret);
44437836SJohn.Forte@Sun.COM }
44447836SJohn.Forte@Sun.COM 
44457836SJohn.Forte@Sun.COM 
44467836SJohn.Forte@Sun.COM /*
44477836SJohn.Forte@Sun.COM  * loadStore
44487836SJohn.Forte@Sun.COM  *
44497836SJohn.Forte@Sun.COM  * Purpose: Load the configuration data from the store
44507836SJohn.Forte@Sun.COM  *
44517836SJohn.Forte@Sun.COM  * First load the host groups and target groups, then the view entries
44527836SJohn.Forte@Sun.COM  * and finally the provider data
44537836SJohn.Forte@Sun.COM  *
44547836SJohn.Forte@Sun.COM  * fd - file descriptor of control node for stmf.
44557836SJohn.Forte@Sun.COM  */
44567836SJohn.Forte@Sun.COM static int
44577836SJohn.Forte@Sun.COM loadStore(int fd)
44587836SJohn.Forte@Sun.COM {
44597836SJohn.Forte@Sun.COM 	int ret;
44607836SJohn.Forte@Sun.COM 	int i, j;
44617836SJohn.Forte@Sun.COM 	stmfGroupList *groupList = NULL;
44627836SJohn.Forte@Sun.COM 	stmfGuidList *guidList = NULL;
44637836SJohn.Forte@Sun.COM 	stmfViewEntryList *viewEntryList = NULL;
44647836SJohn.Forte@Sun.COM 	stmfProviderList *providerList = NULL;
44657836SJohn.Forte@Sun.COM 	int providerType;
44667836SJohn.Forte@Sun.COM 	nvlist_t *nvl = NULL;
44677836SJohn.Forte@Sun.COM 
44687836SJohn.Forte@Sun.COM 
44697836SJohn.Forte@Sun.COM 
44707836SJohn.Forte@Sun.COM 	/* load host groups */
44719585STim.Szeto@Sun.COM 	ret = iLoadGroupFromPs(&groupList, HOST_GROUP);
44727836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
44737836SJohn.Forte@Sun.COM 		return (ret);
44747836SJohn.Forte@Sun.COM 	}
44757836SJohn.Forte@Sun.COM 	ret = loadHostGroups(fd, groupList);
44767836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
44777836SJohn.Forte@Sun.COM 		goto out;
44787836SJohn.Forte@Sun.COM 	}
44797836SJohn.Forte@Sun.COM 
44807836SJohn.Forte@Sun.COM 	stmfFreeMemory(groupList);
44817836SJohn.Forte@Sun.COM 	groupList = NULL;
44827836SJohn.Forte@Sun.COM 
44837836SJohn.Forte@Sun.COM 	/* load target groups */
44849585STim.Szeto@Sun.COM 	ret = iLoadGroupFromPs(&groupList, TARGET_GROUP);
44857836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
44867836SJohn.Forte@Sun.COM 		goto out;
44877836SJohn.Forte@Sun.COM 	}
44887836SJohn.Forte@Sun.COM 	ret = loadTargetGroups(fd, groupList);
44897836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
44907836SJohn.Forte@Sun.COM 		goto out;
44917836SJohn.Forte@Sun.COM 	}
44927836SJohn.Forte@Sun.COM 
44937836SJohn.Forte@Sun.COM 	stmfFreeMemory(groupList);
44947836SJohn.Forte@Sun.COM 	groupList = NULL;
44957836SJohn.Forte@Sun.COM 
44967836SJohn.Forte@Sun.COM 	/* Get the guid list */
44977836SJohn.Forte@Sun.COM 	ret = psGetLogicalUnitList(&guidList);
44987836SJohn.Forte@Sun.COM 	switch (ret) {
44997836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
45007836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
45017836SJohn.Forte@Sun.COM 			break;
45027836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
45037836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
45047836SJohn.Forte@Sun.COM 			break;
45057836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
45067836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
45077836SJohn.Forte@Sun.COM 			break;
45087836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
45097836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
45107836SJohn.Forte@Sun.COM 			break;
45117836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
45127836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
45137836SJohn.Forte@Sun.COM 			break;
45147836SJohn.Forte@Sun.COM 		default:
45157836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
45167836SJohn.Forte@Sun.COM 			break;
45177836SJohn.Forte@Sun.COM 	}
45187836SJohn.Forte@Sun.COM 
45197836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
45207836SJohn.Forte@Sun.COM 		goto out;
45217836SJohn.Forte@Sun.COM 	}
45227836SJohn.Forte@Sun.COM 
45237836SJohn.Forte@Sun.COM 	/*
45247836SJohn.Forte@Sun.COM 	 * We have the guid list, now get the corresponding
45257836SJohn.Forte@Sun.COM 	 * view entries for each guid
45267836SJohn.Forte@Sun.COM 	 */
45277836SJohn.Forte@Sun.COM 	for (i = 0; i < guidList->cnt; i++) {
45287836SJohn.Forte@Sun.COM 		ret = psGetViewEntryList(&guidList->guid[i], &viewEntryList);
45297836SJohn.Forte@Sun.COM 		switch (ret) {
45307836SJohn.Forte@Sun.COM 			case STMF_PS_SUCCESS:
45317836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_SUCCESS;
45327836SJohn.Forte@Sun.COM 				break;
45337836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_NOT_FOUND:
45347836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
45357836SJohn.Forte@Sun.COM 				break;
45367836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_BUSY:
45377836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
45387836SJohn.Forte@Sun.COM 				break;
45397836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_SERVICE_NOT_FOUND:
45407836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_SERVICE_NOT_FOUND;
45417836SJohn.Forte@Sun.COM 				break;
45427836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_VERSION_MISMATCH:
45437836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_SERVICE_DATA_VERSION;
45447836SJohn.Forte@Sun.COM 				break;
45457836SJohn.Forte@Sun.COM 			default:
45467836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
45477836SJohn.Forte@Sun.COM 				break;
45487836SJohn.Forte@Sun.COM 		}
45497836SJohn.Forte@Sun.COM 		if (ret != STMF_STATUS_SUCCESS) {
45507836SJohn.Forte@Sun.COM 			goto out;
45517836SJohn.Forte@Sun.COM 		}
45527836SJohn.Forte@Sun.COM 		for (j = 0; j < viewEntryList->cnt; j++) {
45537836SJohn.Forte@Sun.COM 			ret = addViewEntryIoctl(fd, &guidList->guid[i],
45547836SJohn.Forte@Sun.COM 			    &viewEntryList->ve[j]);
45557836SJohn.Forte@Sun.COM 			if (ret != STMF_STATUS_SUCCESS) {
45567836SJohn.Forte@Sun.COM 				goto out;
45577836SJohn.Forte@Sun.COM 			}
45587836SJohn.Forte@Sun.COM 		}
45597836SJohn.Forte@Sun.COM 	}
45607836SJohn.Forte@Sun.COM 
45617836SJohn.Forte@Sun.COM 	/* get the list of providers that have data */
45627836SJohn.Forte@Sun.COM 	ret = psGetProviderDataList(&providerList);
45637836SJohn.Forte@Sun.COM 	switch (ret) {
45647836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
45657836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
45667836SJohn.Forte@Sun.COM 			break;
45677836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
45687836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
45697836SJohn.Forte@Sun.COM 			break;
45707836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
45717836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
45727836SJohn.Forte@Sun.COM 			break;
45737836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
45747836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
45757836SJohn.Forte@Sun.COM 			break;
45767836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
45777836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
45787836SJohn.Forte@Sun.COM 			break;
45797836SJohn.Forte@Sun.COM 		default:
45807836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
45817836SJohn.Forte@Sun.COM 			break;
45827836SJohn.Forte@Sun.COM 	}
45837836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
45847836SJohn.Forte@Sun.COM 		goto out;
45857836SJohn.Forte@Sun.COM 	}
45867836SJohn.Forte@Sun.COM 
45877836SJohn.Forte@Sun.COM 	for (i = 0; i < providerList->cnt; i++) {
45887836SJohn.Forte@Sun.COM 		providerType = providerList->provider[i].providerType;
45897836SJohn.Forte@Sun.COM 		ret = psGetProviderData(providerList->provider[i].name,
45907836SJohn.Forte@Sun.COM 		    &nvl, providerType, NULL);
45917836SJohn.Forte@Sun.COM 		switch (ret) {
45927836SJohn.Forte@Sun.COM 			case STMF_PS_SUCCESS:
45937836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_SUCCESS;
45947836SJohn.Forte@Sun.COM 				break;
45957836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_NOT_FOUND:
45967836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
45977836SJohn.Forte@Sun.COM 				break;
45987836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_BUSY:
45997836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
46007836SJohn.Forte@Sun.COM 				break;
46017836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_SERVICE_NOT_FOUND:
46027836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_SERVICE_NOT_FOUND;
46037836SJohn.Forte@Sun.COM 				break;
46047836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_VERSION_MISMATCH:
46057836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_SERVICE_DATA_VERSION;
46067836SJohn.Forte@Sun.COM 				break;
46077836SJohn.Forte@Sun.COM 			default:
46087836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
46097836SJohn.Forte@Sun.COM 				break;
46107836SJohn.Forte@Sun.COM 		}
46117836SJohn.Forte@Sun.COM 		if (ret != STMF_STATUS_SUCCESS) {
46127836SJohn.Forte@Sun.COM 			goto out;
46137836SJohn.Forte@Sun.COM 		}
46147836SJohn.Forte@Sun.COM 
46157836SJohn.Forte@Sun.COM 		/* call setProviderData */
46167836SJohn.Forte@Sun.COM 		ret = setProviderData(fd, providerList->provider[i].name, nvl,
46179585STim.Szeto@Sun.COM 		    providerType, NULL);
46187836SJohn.Forte@Sun.COM 		switch (ret) {
46197836SJohn.Forte@Sun.COM 			case STMF_PS_SUCCESS:
46207836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_SUCCESS;
46217836SJohn.Forte@Sun.COM 				break;
46227836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_NOT_FOUND:
46237836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
46247836SJohn.Forte@Sun.COM 				break;
46257836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_BUSY:
46267836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
46277836SJohn.Forte@Sun.COM 				break;
46287836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_SERVICE_NOT_FOUND:
46297836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_SERVICE_NOT_FOUND;
46307836SJohn.Forte@Sun.COM 				break;
46317836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_VERSION_MISMATCH:
46327836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_SERVICE_DATA_VERSION;
46337836SJohn.Forte@Sun.COM 				break;
46347836SJohn.Forte@Sun.COM 			default:
46357836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
46367836SJohn.Forte@Sun.COM 				break;
46377836SJohn.Forte@Sun.COM 		}
46387836SJohn.Forte@Sun.COM 		if (ret != STMF_STATUS_SUCCESS) {
46397836SJohn.Forte@Sun.COM 			goto out;
46407836SJohn.Forte@Sun.COM 		}
46417836SJohn.Forte@Sun.COM 
46427836SJohn.Forte@Sun.COM 		nvlist_free(nvl);
46437836SJohn.Forte@Sun.COM 		nvl = NULL;
46447836SJohn.Forte@Sun.COM 	}
46457836SJohn.Forte@Sun.COM out:
46467836SJohn.Forte@Sun.COM 	if (groupList != NULL) {
46477836SJohn.Forte@Sun.COM 		free(groupList);
46487836SJohn.Forte@Sun.COM 	}
46497836SJohn.Forte@Sun.COM 	if (guidList != NULL) {
46507836SJohn.Forte@Sun.COM 		free(guidList);
46517836SJohn.Forte@Sun.COM 	}
46527836SJohn.Forte@Sun.COM 	if (viewEntryList != NULL) {
46537836SJohn.Forte@Sun.COM 		free(viewEntryList);
46547836SJohn.Forte@Sun.COM 	}
46557836SJohn.Forte@Sun.COM 	if (nvl != NULL) {
46567836SJohn.Forte@Sun.COM 		nvlist_free(nvl);
46577836SJohn.Forte@Sun.COM 	}
46587836SJohn.Forte@Sun.COM 	return (ret);
46597836SJohn.Forte@Sun.COM }
46607836SJohn.Forte@Sun.COM 
46617836SJohn.Forte@Sun.COM /*
46627836SJohn.Forte@Sun.COM  * stmfLoadConfig
46637836SJohn.Forte@Sun.COM  *
46647836SJohn.Forte@Sun.COM  * Purpose - load the configuration data from smf into stmf
46657836SJohn.Forte@Sun.COM  *
46667836SJohn.Forte@Sun.COM  */
46677836SJohn.Forte@Sun.COM int
46687836SJohn.Forte@Sun.COM stmfLoadConfig(void)
46697836SJohn.Forte@Sun.COM {
46709585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
46717836SJohn.Forte@Sun.COM 	int fd;
46727836SJohn.Forte@Sun.COM 	stmf_state_desc_t stmfStateSet;
46737836SJohn.Forte@Sun.COM 	stmfState state;
46747836SJohn.Forte@Sun.COM 
46759585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
46769585STim.Szeto@Sun.COM 		stmfStateSet.state = STMF_STATE_OFFLINE;
46779585STim.Szeto@Sun.COM 		stmfStateSet.config_state = STMF_CONFIG_INIT;
46789585STim.Szeto@Sun.COM 		if ((ret = openStmf(OPEN_EXCL_STMF, &fd))
46799585STim.Szeto@Sun.COM 		    != STMF_STATUS_SUCCESS) {
46809585STim.Szeto@Sun.COM 			return (ret);
46819585STim.Szeto@Sun.COM 		}
46829585STim.Szeto@Sun.COM 		ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE);
46839585STim.Szeto@Sun.COM 		if (ret != STMF_STATUS_SUCCESS) {
46849585STim.Szeto@Sun.COM 			goto done;
46859585STim.Szeto@Sun.COM 		}
46869585STim.Szeto@Sun.COM 		stmfStateSet.config_state = STMF_CONFIG_INIT_DONE;
46879585STim.Szeto@Sun.COM 		goto done;
46889585STim.Szeto@Sun.COM 	}
46897836SJohn.Forte@Sun.COM 
46907836SJohn.Forte@Sun.COM 	/* Check to ensure service exists */
46917836SJohn.Forte@Sun.COM 	if (psCheckService() != STMF_STATUS_SUCCESS) {
46927836SJohn.Forte@Sun.COM 		return (STMF_ERROR_SERVICE_NOT_FOUND);
46937836SJohn.Forte@Sun.COM 	}
46947836SJohn.Forte@Sun.COM 
46957836SJohn.Forte@Sun.COM 	ret = stmfGetState(&state);
46967836SJohn.Forte@Sun.COM 	if (ret == STMF_STATUS_SUCCESS) {
46977836SJohn.Forte@Sun.COM 		if (state.operationalState != STMF_SERVICE_STATE_OFFLINE) {
46987836SJohn.Forte@Sun.COM 			return (STMF_ERROR_SERVICE_ONLINE);
46997836SJohn.Forte@Sun.COM 		}
47007836SJohn.Forte@Sun.COM 	} else {
47017836SJohn.Forte@Sun.COM 		return (STMF_STATUS_ERROR);
47027836SJohn.Forte@Sun.COM 	}
47037836SJohn.Forte@Sun.COM 
47047836SJohn.Forte@Sun.COM 
47057836SJohn.Forte@Sun.COM 	stmfStateSet.state = STMF_STATE_OFFLINE;
47067836SJohn.Forte@Sun.COM 	stmfStateSet.config_state = STMF_CONFIG_INIT;
47077836SJohn.Forte@Sun.COM 
47087836SJohn.Forte@Sun.COM 	/*
47097836SJohn.Forte@Sun.COM 	 * Open control node for stmf
47107836SJohn.Forte@Sun.COM 	 */
47117836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
47127836SJohn.Forte@Sun.COM 		return (ret);
47137836SJohn.Forte@Sun.COM 
47147836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE);
47157836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
47167836SJohn.Forte@Sun.COM 		goto done;
47177836SJohn.Forte@Sun.COM 	}
47187836SJohn.Forte@Sun.COM 
47197836SJohn.Forte@Sun.COM 	/* Load the persistent configuration data */
47207836SJohn.Forte@Sun.COM 	ret = loadStore(fd);
47217836SJohn.Forte@Sun.COM 	if (ret != 0) {
47227836SJohn.Forte@Sun.COM 		goto done;
47237836SJohn.Forte@Sun.COM 	}
47247836SJohn.Forte@Sun.COM 
47257836SJohn.Forte@Sun.COM 	stmfStateSet.state = STMF_STATE_OFFLINE;
47267836SJohn.Forte@Sun.COM 	stmfStateSet.config_state = STMF_CONFIG_INIT_DONE;
47277836SJohn.Forte@Sun.COM 
47287836SJohn.Forte@Sun.COM done:
47297836SJohn.Forte@Sun.COM 	if (ret == STMF_STATUS_SUCCESS) {
47307836SJohn.Forte@Sun.COM 		ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE);
47317836SJohn.Forte@Sun.COM 	}
47327836SJohn.Forte@Sun.COM 	(void) close(fd);
47337836SJohn.Forte@Sun.COM 	return (ret);
47347836SJohn.Forte@Sun.COM }
47357836SJohn.Forte@Sun.COM 
47369585STim.Szeto@Sun.COM 
47377836SJohn.Forte@Sun.COM /*
47387836SJohn.Forte@Sun.COM  * getStmfState
47397836SJohn.Forte@Sun.COM  *
47407836SJohn.Forte@Sun.COM  * stmfState - pointer to stmf_state_desc_t structure. Will contain the state
47417836SJohn.Forte@Sun.COM  *             information of the stmf service on success.
47427836SJohn.Forte@Sun.COM  */
47437836SJohn.Forte@Sun.COM static int
47447836SJohn.Forte@Sun.COM getStmfState(stmf_state_desc_t *stmfState)
47457836SJohn.Forte@Sun.COM {
47467836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
47477836SJohn.Forte@Sun.COM 	int fd;
47487836SJohn.Forte@Sun.COM 	int ioctlRet;
47497836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
47507836SJohn.Forte@Sun.COM 
47517836SJohn.Forte@Sun.COM 	/*
47527836SJohn.Forte@Sun.COM 	 * Open control node for stmf
47537836SJohn.Forte@Sun.COM 	 */
47547836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
47557836SJohn.Forte@Sun.COM 		return (ret);
47567836SJohn.Forte@Sun.COM 
47577836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
47587836SJohn.Forte@Sun.COM 	/*
47597836SJohn.Forte@Sun.COM 	 * Issue ioctl to get the stmf state
47607836SJohn.Forte@Sun.COM 	 */
47617836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
47627836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (stmf_state_desc_t);
47637836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)stmfState;
47647836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = sizeof (stmf_state_desc_t);
47657836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)stmfState;
47667836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_GET_STMF_STATE, &stmfIoctl);
47677836SJohn.Forte@Sun.COM 
47687836SJohn.Forte@Sun.COM 	(void) close(fd);
47697836SJohn.Forte@Sun.COM 
47707836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
47717836SJohn.Forte@Sun.COM 		switch (errno) {
47727836SJohn.Forte@Sun.COM 			case EBUSY:
47737836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
47747836SJohn.Forte@Sun.COM 				break;
47757836SJohn.Forte@Sun.COM 			case EPERM:
47767836SJohn.Forte@Sun.COM 			case EACCES:
47777836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
47787836SJohn.Forte@Sun.COM 				break;
47797836SJohn.Forte@Sun.COM 			default:
47807836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
47817836SJohn.Forte@Sun.COM 				    "getStmfState:ioctl errno(%d)", errno);
47827836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
47837836SJohn.Forte@Sun.COM 				break;
47847836SJohn.Forte@Sun.COM 		}
47857836SJohn.Forte@Sun.COM 	}
47867836SJohn.Forte@Sun.COM 	return (ret);
47877836SJohn.Forte@Sun.COM }
47887836SJohn.Forte@Sun.COM 
47897836SJohn.Forte@Sun.COM 
47907836SJohn.Forte@Sun.COM /*
47917836SJohn.Forte@Sun.COM  * setStmfState
47927836SJohn.Forte@Sun.COM  *
47937836SJohn.Forte@Sun.COM  * stmfState - pointer to caller set state structure
47947836SJohn.Forte@Sun.COM  * objectType - one of:
47957836SJohn.Forte@Sun.COM  *		LOGICAL_UNIT_TYPE
47967836SJohn.Forte@Sun.COM  *		TARGET_TYPE
47977836SJohn.Forte@Sun.COM  *		STMF_SERVICE_TYPE
47987836SJohn.Forte@Sun.COM  */
47997836SJohn.Forte@Sun.COM static int
48007836SJohn.Forte@Sun.COM setStmfState(int fd, stmf_state_desc_t *stmfState, int objectType)
48017836SJohn.Forte@Sun.COM {
48027836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
48037836SJohn.Forte@Sun.COM 	int ioctlRet;
48047836SJohn.Forte@Sun.COM 	int cmd;
48057836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
48067836SJohn.Forte@Sun.COM 
48077836SJohn.Forte@Sun.COM 	switch (objectType) {
48087836SJohn.Forte@Sun.COM 		case LOGICAL_UNIT_TYPE:
48097836SJohn.Forte@Sun.COM 			cmd = STMF_IOCTL_SET_LU_STATE;
48107836SJohn.Forte@Sun.COM 			break;
48117836SJohn.Forte@Sun.COM 		case TARGET_TYPE:
48127836SJohn.Forte@Sun.COM 			cmd = STMF_IOCTL_SET_TARGET_PORT_STATE;
48137836SJohn.Forte@Sun.COM 			break;
48147836SJohn.Forte@Sun.COM 		case STMF_SERVICE_TYPE:
48157836SJohn.Forte@Sun.COM 			cmd = STMF_IOCTL_SET_STMF_STATE;
48167836SJohn.Forte@Sun.COM 			break;
48177836SJohn.Forte@Sun.COM 		default:
48187836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
48197836SJohn.Forte@Sun.COM 			goto done;
48207836SJohn.Forte@Sun.COM 	}
48217836SJohn.Forte@Sun.COM 
48227836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
48237836SJohn.Forte@Sun.COM 	/*
48247836SJohn.Forte@Sun.COM 	 * Issue ioctl to set the stmf state
48257836SJohn.Forte@Sun.COM 	 */
48267836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
48277836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (stmf_state_desc_t);
48287836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)stmfState;
48297836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
48307836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
48317836SJohn.Forte@Sun.COM 		switch (errno) {
48327836SJohn.Forte@Sun.COM 			case EBUSY:
48337836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
48347836SJohn.Forte@Sun.COM 				break;
48359585STim.Szeto@Sun.COM 			case EPERM:
48367836SJohn.Forte@Sun.COM 			case EACCES:
48377836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
48387836SJohn.Forte@Sun.COM 				break;
48397836SJohn.Forte@Sun.COM 			case ENOENT:
48407836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
48417836SJohn.Forte@Sun.COM 				break;
48427836SJohn.Forte@Sun.COM 			default:
48437836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
48447836SJohn.Forte@Sun.COM 				    "setStmfState:ioctl errno(%d)", errno);
48457836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
48467836SJohn.Forte@Sun.COM 				break;
48477836SJohn.Forte@Sun.COM 		}
48487836SJohn.Forte@Sun.COM 	}
48497836SJohn.Forte@Sun.COM done:
48507836SJohn.Forte@Sun.COM 	return (ret);
48517836SJohn.Forte@Sun.COM }
48527836SJohn.Forte@Sun.COM 
48537836SJohn.Forte@Sun.COM /*
48547836SJohn.Forte@Sun.COM  * stmfOnline
48557836SJohn.Forte@Sun.COM  *
48567836SJohn.Forte@Sun.COM  * Purpose: Online stmf service
48577836SJohn.Forte@Sun.COM  *
48587836SJohn.Forte@Sun.COM  */
48597836SJohn.Forte@Sun.COM int
48607836SJohn.Forte@Sun.COM stmfOnline(void)
48617836SJohn.Forte@Sun.COM {
48627836SJohn.Forte@Sun.COM 	int ret;
48637836SJohn.Forte@Sun.COM 	int fd;
48647836SJohn.Forte@Sun.COM 	stmfState state;
48657836SJohn.Forte@Sun.COM 	stmf_state_desc_t iState;
48667836SJohn.Forte@Sun.COM 
48677836SJohn.Forte@Sun.COM 	ret = stmfGetState(&state);
48687836SJohn.Forte@Sun.COM 	if (ret == STMF_STATUS_SUCCESS) {
48697836SJohn.Forte@Sun.COM 		if (state.operationalState == STMF_SERVICE_STATE_ONLINE) {
48707836SJohn.Forte@Sun.COM 			return (STMF_ERROR_SERVICE_ONLINE);
48717836SJohn.Forte@Sun.COM 		}
48727836SJohn.Forte@Sun.COM 	} else {
48737836SJohn.Forte@Sun.COM 		return (STMF_STATUS_ERROR);
48747836SJohn.Forte@Sun.COM 	}
48757836SJohn.Forte@Sun.COM 	iState.state = STMF_STATE_ONLINE;
48767836SJohn.Forte@Sun.COM 	iState.config_state = STMF_CONFIG_NONE;
48777836SJohn.Forte@Sun.COM 	/*
48787836SJohn.Forte@Sun.COM 	 * Open control node for stmf
48797836SJohn.Forte@Sun.COM 	 * to make call to setStmfState()
48807836SJohn.Forte@Sun.COM 	 */
48817836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
48827836SJohn.Forte@Sun.COM 		return (ret);
48837836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &iState, STMF_SERVICE_TYPE);
48847836SJohn.Forte@Sun.COM 	(void) close(fd);
48857836SJohn.Forte@Sun.COM 	return (ret);
48867836SJohn.Forte@Sun.COM }
48877836SJohn.Forte@Sun.COM 
48887836SJohn.Forte@Sun.COM /*
48897836SJohn.Forte@Sun.COM  * stmfOffline
48907836SJohn.Forte@Sun.COM  *
48917836SJohn.Forte@Sun.COM  * Purpose: Offline stmf service
48927836SJohn.Forte@Sun.COM  *
48937836SJohn.Forte@Sun.COM  */
48947836SJohn.Forte@Sun.COM int
48957836SJohn.Forte@Sun.COM stmfOffline(void)
48967836SJohn.Forte@Sun.COM {
48977836SJohn.Forte@Sun.COM 	int ret;
48987836SJohn.Forte@Sun.COM 	int fd;
48997836SJohn.Forte@Sun.COM 	stmfState state;
49007836SJohn.Forte@Sun.COM 	stmf_state_desc_t iState;
49017836SJohn.Forte@Sun.COM 
49027836SJohn.Forte@Sun.COM 	ret = stmfGetState(&state);
49037836SJohn.Forte@Sun.COM 	if (ret == STMF_STATUS_SUCCESS) {
49047836SJohn.Forte@Sun.COM 		if (state.operationalState == STMF_SERVICE_STATE_OFFLINE) {
49057836SJohn.Forte@Sun.COM 			return (STMF_ERROR_SERVICE_OFFLINE);
49067836SJohn.Forte@Sun.COM 		}
49077836SJohn.Forte@Sun.COM 	} else {
49087836SJohn.Forte@Sun.COM 		return (STMF_STATUS_ERROR);
49097836SJohn.Forte@Sun.COM 	}
49107836SJohn.Forte@Sun.COM 	iState.state = STMF_STATE_OFFLINE;
49117836SJohn.Forte@Sun.COM 	iState.config_state = STMF_CONFIG_NONE;
49127836SJohn.Forte@Sun.COM 
49137836SJohn.Forte@Sun.COM 	/*
49147836SJohn.Forte@Sun.COM 	 * Open control node for stmf
49157836SJohn.Forte@Sun.COM 	 * to make call to setStmfState()
49167836SJohn.Forte@Sun.COM 	 */
49177836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
49187836SJohn.Forte@Sun.COM 		return (ret);
49197836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &iState, STMF_SERVICE_TYPE);
49207836SJohn.Forte@Sun.COM 	(void) close(fd);
49217836SJohn.Forte@Sun.COM 	return (ret);
49227836SJohn.Forte@Sun.COM }
49237836SJohn.Forte@Sun.COM 
49247836SJohn.Forte@Sun.COM 
49257836SJohn.Forte@Sun.COM /*
49267836SJohn.Forte@Sun.COM  * stmfOfflineTarget
49277836SJohn.Forte@Sun.COM  *
49287836SJohn.Forte@Sun.COM  * Purpose: Change state of target to offline
49297836SJohn.Forte@Sun.COM  *
49307836SJohn.Forte@Sun.COM  * devid - devid of the target to offline
49317836SJohn.Forte@Sun.COM  */
49327836SJohn.Forte@Sun.COM int
49337836SJohn.Forte@Sun.COM stmfOfflineTarget(stmfDevid *devid)
49347836SJohn.Forte@Sun.COM {
49357836SJohn.Forte@Sun.COM 	stmf_state_desc_t targetState;
49367836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
49377836SJohn.Forte@Sun.COM 	int fd;
49387836SJohn.Forte@Sun.COM 
49397836SJohn.Forte@Sun.COM 	if (devid == NULL) {
49407836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
49417836SJohn.Forte@Sun.COM 	}
49427836SJohn.Forte@Sun.COM 	bzero(&targetState, sizeof (targetState));
49437836SJohn.Forte@Sun.COM 
49447836SJohn.Forte@Sun.COM 	targetState.state = STMF_STATE_OFFLINE;
49457836SJohn.Forte@Sun.COM 	targetState.ident[IDENT_LENGTH_BYTE] = devid->identLength;
49467836SJohn.Forte@Sun.COM 	bcopy(&(devid->ident), &targetState.ident[IDENT_LENGTH_BYTE + 1],
49477836SJohn.Forte@Sun.COM 	    devid->identLength);
49487836SJohn.Forte@Sun.COM 	/*
49497836SJohn.Forte@Sun.COM 	 * Open control node for stmf
49507836SJohn.Forte@Sun.COM 	 * to make call to setStmfState()
49517836SJohn.Forte@Sun.COM 	 */
49527836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
49537836SJohn.Forte@Sun.COM 		return (ret);
49547836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &targetState, TARGET_TYPE);
49557836SJohn.Forte@Sun.COM 	(void) close(fd);
49567836SJohn.Forte@Sun.COM 	return (ret);
49577836SJohn.Forte@Sun.COM }
49587836SJohn.Forte@Sun.COM 
49597836SJohn.Forte@Sun.COM /*
49607836SJohn.Forte@Sun.COM  * stmfOfflineLogicalUnit
49617836SJohn.Forte@Sun.COM  *
49627836SJohn.Forte@Sun.COM  * Purpose: Change state of logical unit to offline
49637836SJohn.Forte@Sun.COM  *
49647836SJohn.Forte@Sun.COM  * lu - guid of the logical unit to offline
49657836SJohn.Forte@Sun.COM  */
49667836SJohn.Forte@Sun.COM int
49677836SJohn.Forte@Sun.COM stmfOfflineLogicalUnit(stmfGuid *lu)
49687836SJohn.Forte@Sun.COM {
49697836SJohn.Forte@Sun.COM 	stmf_state_desc_t luState;
49707836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
49717836SJohn.Forte@Sun.COM 	int fd;
49727836SJohn.Forte@Sun.COM 
49737836SJohn.Forte@Sun.COM 	if (lu == NULL) {
49747836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
49757836SJohn.Forte@Sun.COM 	}
49767836SJohn.Forte@Sun.COM 
49777836SJohn.Forte@Sun.COM 	bzero(&luState, sizeof (luState));
49787836SJohn.Forte@Sun.COM 
49797836SJohn.Forte@Sun.COM 	luState.state = STMF_STATE_OFFLINE;
49807836SJohn.Forte@Sun.COM 	bcopy(lu, &luState.ident, sizeof (stmfGuid));
49817836SJohn.Forte@Sun.COM 	/*
49827836SJohn.Forte@Sun.COM 	 * Open control node for stmf
49837836SJohn.Forte@Sun.COM 	 * to make call to setStmfState()
49847836SJohn.Forte@Sun.COM 	 */
49857836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
49867836SJohn.Forte@Sun.COM 		return (ret);
49877836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &luState, LOGICAL_UNIT_TYPE);
49887836SJohn.Forte@Sun.COM 	(void) close(fd);
49897836SJohn.Forte@Sun.COM 	return (ret);
49907836SJohn.Forte@Sun.COM }
49917836SJohn.Forte@Sun.COM 
49927836SJohn.Forte@Sun.COM /*
49937836SJohn.Forte@Sun.COM  * stmfOnlineTarget
49947836SJohn.Forte@Sun.COM  *
49957836SJohn.Forte@Sun.COM  * Purpose: Change state of target to online
49967836SJohn.Forte@Sun.COM  *
49977836SJohn.Forte@Sun.COM  * devid - devid of the target to online
49987836SJohn.Forte@Sun.COM  */
49997836SJohn.Forte@Sun.COM int
50007836SJohn.Forte@Sun.COM stmfOnlineTarget(stmfDevid *devid)
50017836SJohn.Forte@Sun.COM {
50027836SJohn.Forte@Sun.COM 	stmf_state_desc_t targetState;
50037836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
50047836SJohn.Forte@Sun.COM 	int fd;
50057836SJohn.Forte@Sun.COM 
50067836SJohn.Forte@Sun.COM 	if (devid == NULL) {
50077836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
50087836SJohn.Forte@Sun.COM 	}
50097836SJohn.Forte@Sun.COM 	bzero(&targetState, sizeof (targetState));
50107836SJohn.Forte@Sun.COM 
50117836SJohn.Forte@Sun.COM 	targetState.state = STMF_STATE_ONLINE;
50127836SJohn.Forte@Sun.COM 	targetState.ident[IDENT_LENGTH_BYTE] = devid->identLength;
50137836SJohn.Forte@Sun.COM 	bcopy(&(devid->ident), &targetState.ident[IDENT_LENGTH_BYTE + 1],
50147836SJohn.Forte@Sun.COM 	    devid->identLength);
50157836SJohn.Forte@Sun.COM 	/*
50167836SJohn.Forte@Sun.COM 	 * Open control node for stmf
50177836SJohn.Forte@Sun.COM 	 * to make call to setStmfState()
50187836SJohn.Forte@Sun.COM 	 */
50197836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
50207836SJohn.Forte@Sun.COM 		return (ret);
50217836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &targetState, TARGET_TYPE);
50227836SJohn.Forte@Sun.COM 	(void) close(fd);
50237836SJohn.Forte@Sun.COM 	return (ret);
50247836SJohn.Forte@Sun.COM }
50257836SJohn.Forte@Sun.COM 
50267836SJohn.Forte@Sun.COM /*
50277836SJohn.Forte@Sun.COM  * stmfOnlineLogicalUnit
50287836SJohn.Forte@Sun.COM  *
50297836SJohn.Forte@Sun.COM  * Purpose: Change state of logical unit to online
50307836SJohn.Forte@Sun.COM  *
50317836SJohn.Forte@Sun.COM  * lu - guid of the logical unit to online
50327836SJohn.Forte@Sun.COM  */
50337836SJohn.Forte@Sun.COM int
50347836SJohn.Forte@Sun.COM stmfOnlineLogicalUnit(stmfGuid *lu)
50357836SJohn.Forte@Sun.COM {
50367836SJohn.Forte@Sun.COM 	stmf_state_desc_t luState;
50377836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
50387836SJohn.Forte@Sun.COM 	int fd;
50397836SJohn.Forte@Sun.COM 
50407836SJohn.Forte@Sun.COM 	if (lu == NULL) {
50417836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
50427836SJohn.Forte@Sun.COM 	}
50437836SJohn.Forte@Sun.COM 
50447836SJohn.Forte@Sun.COM 	bzero(&luState, sizeof (luState));
50457836SJohn.Forte@Sun.COM 
50467836SJohn.Forte@Sun.COM 	luState.state = STMF_STATE_ONLINE;
50477836SJohn.Forte@Sun.COM 	bcopy(lu, &luState.ident, sizeof (stmfGuid));
50487836SJohn.Forte@Sun.COM 	/*
50497836SJohn.Forte@Sun.COM 	 * Open control node for stmf
50507836SJohn.Forte@Sun.COM 	 * to make call to setStmfState()
50517836SJohn.Forte@Sun.COM 	 */
50527836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
50537836SJohn.Forte@Sun.COM 		return (ret);
50547836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &luState, LOGICAL_UNIT_TYPE);
50557836SJohn.Forte@Sun.COM 	(void) close(fd);
50567836SJohn.Forte@Sun.COM 	return (ret);
50577836SJohn.Forte@Sun.COM }
50587836SJohn.Forte@Sun.COM 
50597836SJohn.Forte@Sun.COM /*
50607836SJohn.Forte@Sun.COM  * stmfRemoveFromHostGroup
50617836SJohn.Forte@Sun.COM  *
50627836SJohn.Forte@Sun.COM  * Purpose: Removes an initiator from an initiator group
50637836SJohn.Forte@Sun.COM  *
50647836SJohn.Forte@Sun.COM  * hostGroupName - name of an initiator group
50657836SJohn.Forte@Sun.COM  * hostName - name of host group member to remove
50667836SJohn.Forte@Sun.COM  */
50677836SJohn.Forte@Sun.COM int
50687836SJohn.Forte@Sun.COM stmfRemoveFromHostGroup(stmfGroupName *hostGroupName, stmfDevid *hostName)
50697836SJohn.Forte@Sun.COM {
50707836SJohn.Forte@Sun.COM 	int ret;
50717836SJohn.Forte@Sun.COM 	int fd;
50727836SJohn.Forte@Sun.COM 
50737836SJohn.Forte@Sun.COM 	if (hostGroupName == NULL ||
50747836SJohn.Forte@Sun.COM 	    (strnlen((char *)hostGroupName, sizeof (stmfGroupName))
50757836SJohn.Forte@Sun.COM 	    == sizeof (stmfGroupName)) || hostName == NULL) {
50767836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
50777836SJohn.Forte@Sun.COM 	}
50787836SJohn.Forte@Sun.COM 
50797836SJohn.Forte@Sun.COM 	/* call init */
50807836SJohn.Forte@Sun.COM 	ret = initializeConfig();
50817836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
50827836SJohn.Forte@Sun.COM 		return (ret);
50837836SJohn.Forte@Sun.COM 	}
50847836SJohn.Forte@Sun.COM 
50857836SJohn.Forte@Sun.COM 	/*
50867836SJohn.Forte@Sun.COM 	 * Open control node for stmf
50877836SJohn.Forte@Sun.COM 	 */
50887836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
50897836SJohn.Forte@Sun.COM 		return (ret);
50907836SJohn.Forte@Sun.COM 
50917836SJohn.Forte@Sun.COM 	if ((ret = groupMemberIoctl(fd, STMF_IOCTL_REMOVE_HG_ENTRY,
50927836SJohn.Forte@Sun.COM 	    hostGroupName, hostName)) != STMF_STATUS_SUCCESS) {
50937836SJohn.Forte@Sun.COM 		goto done;
50947836SJohn.Forte@Sun.COM 	}
50957836SJohn.Forte@Sun.COM 
50969585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
50979585STim.Szeto@Sun.COM 		goto done;
50989585STim.Szeto@Sun.COM 	}
50999585STim.Szeto@Sun.COM 
51007836SJohn.Forte@Sun.COM 	ret = psRemoveHostGroupMember((char *)hostGroupName,
51017836SJohn.Forte@Sun.COM 	    (char *)hostName->ident);
51027836SJohn.Forte@Sun.COM 	switch (ret) {
51037836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
51047836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
51057836SJohn.Forte@Sun.COM 			break;
51067836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_MEMBER_NOT_FOUND:
51077836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_MEMBER_NOT_FOUND;
51087836SJohn.Forte@Sun.COM 			break;
51097836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_GROUP_NOT_FOUND:
51107836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_GROUP_NOT_FOUND;
51117836SJohn.Forte@Sun.COM 			break;
51127836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
51137836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
51147836SJohn.Forte@Sun.COM 			break;
51157836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
51167836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
51177836SJohn.Forte@Sun.COM 			break;
51187836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
51197836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
51207836SJohn.Forte@Sun.COM 			break;
51217836SJohn.Forte@Sun.COM 		default:
51227836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
51237836SJohn.Forte@Sun.COM 			    "stmfRemoveFromHostGroup"
51247836SJohn.Forte@Sun.COM 			    "psRemoveHostGroupMember:error(%d)", ret);
51257836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
51267836SJohn.Forte@Sun.COM 			break;
51277836SJohn.Forte@Sun.COM 	}
51287836SJohn.Forte@Sun.COM 
51297836SJohn.Forte@Sun.COM done:
51307836SJohn.Forte@Sun.COM 	(void) close(fd);
51317836SJohn.Forte@Sun.COM 	return (ret);
51327836SJohn.Forte@Sun.COM }
51337836SJohn.Forte@Sun.COM 
51347836SJohn.Forte@Sun.COM /*
51357836SJohn.Forte@Sun.COM  * stmfRemoveFromTargetGroup
51367836SJohn.Forte@Sun.COM  *
51377836SJohn.Forte@Sun.COM  * Purpose: Removes a local port from a local port group
51387836SJohn.Forte@Sun.COM  *
51397836SJohn.Forte@Sun.COM  * targetGroupName - name of a target group
51407836SJohn.Forte@Sun.COM  * targetName - name of target to remove
51417836SJohn.Forte@Sun.COM  */
51427836SJohn.Forte@Sun.COM int
51437836SJohn.Forte@Sun.COM stmfRemoveFromTargetGroup(stmfGroupName *targetGroupName, stmfDevid *targetName)
51447836SJohn.Forte@Sun.COM {
51457836SJohn.Forte@Sun.COM 	int ret;
51467836SJohn.Forte@Sun.COM 	int fd;
51477836SJohn.Forte@Sun.COM 
51487836SJohn.Forte@Sun.COM 	if (targetGroupName == NULL ||
51497836SJohn.Forte@Sun.COM 	    (strnlen((char *)targetGroupName, sizeof (stmfGroupName))
51507836SJohn.Forte@Sun.COM 	    == sizeof (stmfGroupName)) || targetName == NULL) {
51517836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
51527836SJohn.Forte@Sun.COM 	}
51537836SJohn.Forte@Sun.COM 
51547836SJohn.Forte@Sun.COM 	/* call init */
51557836SJohn.Forte@Sun.COM 	ret = initializeConfig();
51567836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
51577836SJohn.Forte@Sun.COM 		return (ret);
51587836SJohn.Forte@Sun.COM 	}
51597836SJohn.Forte@Sun.COM 
51607836SJohn.Forte@Sun.COM 	/*
51617836SJohn.Forte@Sun.COM 	 * Open control node for stmf
51627836SJohn.Forte@Sun.COM 	 */
51637836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
51647836SJohn.Forte@Sun.COM 		return (ret);
51657836SJohn.Forte@Sun.COM 
51667836SJohn.Forte@Sun.COM 	if ((ret = groupMemberIoctl(fd, STMF_IOCTL_REMOVE_TG_ENTRY,
51677836SJohn.Forte@Sun.COM 	    targetGroupName, targetName)) != STMF_STATUS_SUCCESS) {
51687836SJohn.Forte@Sun.COM 		goto done;
51697836SJohn.Forte@Sun.COM 	}
51707836SJohn.Forte@Sun.COM 
51719585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
51729585STim.Szeto@Sun.COM 		goto done;
51739585STim.Szeto@Sun.COM 	}
51749585STim.Szeto@Sun.COM 
51757836SJohn.Forte@Sun.COM 	ret = psRemoveTargetGroupMember((char *)targetGroupName,
51767836SJohn.Forte@Sun.COM 	    (char *)targetName->ident);
51777836SJohn.Forte@Sun.COM 	switch (ret) {
51787836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
51797836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
51807836SJohn.Forte@Sun.COM 			break;
51817836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_MEMBER_NOT_FOUND:
51827836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_MEMBER_NOT_FOUND;
51837836SJohn.Forte@Sun.COM 			break;
51847836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_GROUP_NOT_FOUND:
51857836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_GROUP_NOT_FOUND;
51867836SJohn.Forte@Sun.COM 			break;
51877836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
51887836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
51897836SJohn.Forte@Sun.COM 			break;
51907836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
51917836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
51927836SJohn.Forte@Sun.COM 			break;
51937836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
51947836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
51957836SJohn.Forte@Sun.COM 			break;
51967836SJohn.Forte@Sun.COM 		default:
51977836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
51987836SJohn.Forte@Sun.COM 			    "stmfRemoveFromTargetGroup"
51997836SJohn.Forte@Sun.COM 			    "psRemoveTargetGroupMember:error(%d)", ret);
52007836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
52017836SJohn.Forte@Sun.COM 			break;
52027836SJohn.Forte@Sun.COM 	}
52037836SJohn.Forte@Sun.COM 
52047836SJohn.Forte@Sun.COM done:
52057836SJohn.Forte@Sun.COM 	(void) close(fd);
52067836SJohn.Forte@Sun.COM 	return (ret);
52077836SJohn.Forte@Sun.COM }
52087836SJohn.Forte@Sun.COM 
52097836SJohn.Forte@Sun.COM /*
52107836SJohn.Forte@Sun.COM  * stmfRemoveViewEntry
52117836SJohn.Forte@Sun.COM  *
52127836SJohn.Forte@Sun.COM  * Purpose: Removes a view entry from a logical unit
52137836SJohn.Forte@Sun.COM  *
52147836SJohn.Forte@Sun.COM  * lu - guid of lu for which view entry is being removed
52157836SJohn.Forte@Sun.COM  * viewEntryIndex - index of view entry to remove
52167836SJohn.Forte@Sun.COM  *
52177836SJohn.Forte@Sun.COM  */
52187836SJohn.Forte@Sun.COM int
52197836SJohn.Forte@Sun.COM stmfRemoveViewEntry(stmfGuid *lu, uint32_t viewEntryIndex)
52207836SJohn.Forte@Sun.COM {
52217836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
52227836SJohn.Forte@Sun.COM 	int fd;
52237836SJohn.Forte@Sun.COM 	int ioctlRet;
52247836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
52257836SJohn.Forte@Sun.COM 	stmf_view_op_entry_t ioctlViewEntry;
52267836SJohn.Forte@Sun.COM 
52277836SJohn.Forte@Sun.COM 	if (lu == NULL) {
52287836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
52297836SJohn.Forte@Sun.COM 	}
52307836SJohn.Forte@Sun.COM 
52317836SJohn.Forte@Sun.COM 	/* call init */
52327836SJohn.Forte@Sun.COM 	ret = initializeConfig();
52337836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
52347836SJohn.Forte@Sun.COM 		return (ret);
52357836SJohn.Forte@Sun.COM 	}
52367836SJohn.Forte@Sun.COM 
52377836SJohn.Forte@Sun.COM 	/*
52387836SJohn.Forte@Sun.COM 	 * Open control node for stmf
52397836SJohn.Forte@Sun.COM 	 */
52407836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
52417836SJohn.Forte@Sun.COM 		return (ret);
52427836SJohn.Forte@Sun.COM 
52437836SJohn.Forte@Sun.COM 	bzero(&ioctlViewEntry, sizeof (ioctlViewEntry));
52447836SJohn.Forte@Sun.COM 	ioctlViewEntry.ve_ndx_valid = B_TRUE;
52457836SJohn.Forte@Sun.COM 	ioctlViewEntry.ve_ndx = viewEntryIndex;
52467836SJohn.Forte@Sun.COM 	bcopy(lu, &ioctlViewEntry.ve_guid, sizeof (stmfGuid));
52477836SJohn.Forte@Sun.COM 
52487836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
52497836SJohn.Forte@Sun.COM 	/*
52507836SJohn.Forte@Sun.COM 	 * Issue ioctl to add to the view entry
52517836SJohn.Forte@Sun.COM 	 */
52527836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
52537836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry);
52547836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry;
52557836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_REMOVE_VIEW_ENTRY, &stmfIoctl);
52567836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
52577836SJohn.Forte@Sun.COM 		switch (errno) {
52587836SJohn.Forte@Sun.COM 			case EBUSY:
52597836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
52607836SJohn.Forte@Sun.COM 				break;
52619585STim.Szeto@Sun.COM 			case EPERM:
52629585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
52639585STim.Szeto@Sun.COM 				break;
52647836SJohn.Forte@Sun.COM 			case EACCES:
52657836SJohn.Forte@Sun.COM 				switch (stmfIoctl.stmf_error) {
52667836SJohn.Forte@Sun.COM 					case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
52677836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_CONFIG_NONE;
52687836SJohn.Forte@Sun.COM 						break;
52697836SJohn.Forte@Sun.COM 					default:
52707836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_PERM;
52717836SJohn.Forte@Sun.COM 						break;
52727836SJohn.Forte@Sun.COM 				}
52737836SJohn.Forte@Sun.COM 				break;
52747836SJohn.Forte@Sun.COM 			case ENODEV:
52757836SJohn.Forte@Sun.COM 			case ENOENT:
52767836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
52777836SJohn.Forte@Sun.COM 				break;
52787836SJohn.Forte@Sun.COM 			default:
52797836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
52807836SJohn.Forte@Sun.COM 				    "stmfRemoveViewEntry:ioctl errno(%d)",
52817836SJohn.Forte@Sun.COM 				    errno);
52827836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
52837836SJohn.Forte@Sun.COM 				break;
52847836SJohn.Forte@Sun.COM 		}
52857836SJohn.Forte@Sun.COM 		goto done;
52867836SJohn.Forte@Sun.COM 	}
52877836SJohn.Forte@Sun.COM 
52889585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
52899585STim.Szeto@Sun.COM 		goto done;
52909585STim.Szeto@Sun.COM 	}
52919585STim.Szeto@Sun.COM 
52927836SJohn.Forte@Sun.COM 	ret = psRemoveViewEntry(lu, viewEntryIndex);
52937836SJohn.Forte@Sun.COM 	switch (ret) {
52947836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
52957836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
52967836SJohn.Forte@Sun.COM 			break;
52977836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
52987836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
52997836SJohn.Forte@Sun.COM 			break;
53007836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
53017836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
53027836SJohn.Forte@Sun.COM 			break;
53037836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
53047836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
53057836SJohn.Forte@Sun.COM 			break;
53067836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
53077836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
53087836SJohn.Forte@Sun.COM 			break;
53097836SJohn.Forte@Sun.COM 		default:
53107836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
53117836SJohn.Forte@Sun.COM 			    "stmfRemoveViewEntry" "psRemoveViewEntry:error(%d)",
53127836SJohn.Forte@Sun.COM 			    ret);
53137836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
53147836SJohn.Forte@Sun.COM 			break;
53157836SJohn.Forte@Sun.COM 	}
53167836SJohn.Forte@Sun.COM 
53177836SJohn.Forte@Sun.COM done:
53187836SJohn.Forte@Sun.COM 	(void) close(fd);
53197836SJohn.Forte@Sun.COM 	return (ret);
53207836SJohn.Forte@Sun.COM }
53217836SJohn.Forte@Sun.COM 
53227836SJohn.Forte@Sun.COM /*
53237836SJohn.Forte@Sun.COM  * stmfSetProviderData
53247836SJohn.Forte@Sun.COM  *
53257836SJohn.Forte@Sun.COM  * Purpose: set the provider data
53267836SJohn.Forte@Sun.COM  *
53277836SJohn.Forte@Sun.COM  * providerName - unique name of provider
53287836SJohn.Forte@Sun.COM  * nvl - nvlist to set
53297836SJohn.Forte@Sun.COM  * providerType - type of provider for which to set data
53307836SJohn.Forte@Sun.COM  *		STMF_LU_PROVIDER_TYPE
53317836SJohn.Forte@Sun.COM  *		STMF_PORT_PROVIDER_TYPE
53327836SJohn.Forte@Sun.COM  */
53337836SJohn.Forte@Sun.COM int
53347836SJohn.Forte@Sun.COM stmfSetProviderData(char *providerName, nvlist_t *nvl, int providerType)
53357836SJohn.Forte@Sun.COM {
53367836SJohn.Forte@Sun.COM 	return (stmfSetProviderDataProt(providerName, nvl, providerType,
53377836SJohn.Forte@Sun.COM 	    NULL));
53387836SJohn.Forte@Sun.COM }
53397836SJohn.Forte@Sun.COM 
53407836SJohn.Forte@Sun.COM /*
53417836SJohn.Forte@Sun.COM  * stmfSetProviderDataProt
53427836SJohn.Forte@Sun.COM  *
53437836SJohn.Forte@Sun.COM  * Purpose: set the provider data
53447836SJohn.Forte@Sun.COM  *
53457836SJohn.Forte@Sun.COM  * providerName - unique name of provider
53467836SJohn.Forte@Sun.COM  * nvl - nvlist to set
53477836SJohn.Forte@Sun.COM  * providerType - type of provider for which to set data
53487836SJohn.Forte@Sun.COM  *		STMF_LU_PROVIDER_TYPE
53497836SJohn.Forte@Sun.COM  *		STMF_PORT_PROVIDER_TYPE
53507836SJohn.Forte@Sun.COM  * setToken - Stale data token returned in the stmfGetProviderDataProt()
53517836SJohn.Forte@Sun.COM  *	      call or NULL.
53527836SJohn.Forte@Sun.COM  */
53537836SJohn.Forte@Sun.COM int
53547836SJohn.Forte@Sun.COM stmfSetProviderDataProt(char *providerName, nvlist_t *nvl, int providerType,
53557836SJohn.Forte@Sun.COM     uint64_t *setToken)
53567836SJohn.Forte@Sun.COM {
53577836SJohn.Forte@Sun.COM 	int ret;
53587836SJohn.Forte@Sun.COM 	int fd;
53597836SJohn.Forte@Sun.COM 
53607836SJohn.Forte@Sun.COM 	if (providerName == NULL || nvl == NULL) {
53617836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
53627836SJohn.Forte@Sun.COM 	}
53637836SJohn.Forte@Sun.COM 
53647836SJohn.Forte@Sun.COM 	if (providerType != STMF_LU_PROVIDER_TYPE &&
53657836SJohn.Forte@Sun.COM 	    providerType != STMF_PORT_PROVIDER_TYPE) {
53667836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
53677836SJohn.Forte@Sun.COM 	}
53687836SJohn.Forte@Sun.COM 
53697836SJohn.Forte@Sun.COM 	/* call init */
53707836SJohn.Forte@Sun.COM 	ret = initializeConfig();
53717836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
53727836SJohn.Forte@Sun.COM 		return (ret);
53737836SJohn.Forte@Sun.COM 	}
53747836SJohn.Forte@Sun.COM 
53757836SJohn.Forte@Sun.COM 	/*
53767836SJohn.Forte@Sun.COM 	 * Open control node for stmf
53777836SJohn.Forte@Sun.COM 	 */
53787836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
53797836SJohn.Forte@Sun.COM 		return (ret);
53807836SJohn.Forte@Sun.COM 
53819585STim.Szeto@Sun.COM 	ret = setProviderData(fd, providerName, nvl, providerType, setToken);
53827836SJohn.Forte@Sun.COM 
53837836SJohn.Forte@Sun.COM 	(void) close(fd);
53847836SJohn.Forte@Sun.COM 
53857836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
53867836SJohn.Forte@Sun.COM 		goto done;
53877836SJohn.Forte@Sun.COM 	}
53887836SJohn.Forte@Sun.COM 
53899585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
53909585STim.Szeto@Sun.COM 		goto done;
53919585STim.Szeto@Sun.COM 	}
53929585STim.Szeto@Sun.COM 
53937836SJohn.Forte@Sun.COM 	/* setting driver provider data successful. Now persist it */
53949585STim.Szeto@Sun.COM 	ret = psSetProviderData(providerName, nvl, providerType, NULL);
53957836SJohn.Forte@Sun.COM 	switch (ret) {
53967836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
53977836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
53987836SJohn.Forte@Sun.COM 			break;
53997836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_EXISTS:
54007836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_EXISTS;
54017836SJohn.Forte@Sun.COM 			break;
54027836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
54037836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
54047836SJohn.Forte@Sun.COM 			break;
54057836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
54067836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
54077836SJohn.Forte@Sun.COM 			break;
54087836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
54097836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
54107836SJohn.Forte@Sun.COM 			break;
54117836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_PROV_DATA_STALE:
54127836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_PROV_DATA_STALE;
54137836SJohn.Forte@Sun.COM 			break;
54147836SJohn.Forte@Sun.COM 		default:
54157836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
54167836SJohn.Forte@Sun.COM 			    "stmfSetProviderData"
54177836SJohn.Forte@Sun.COM 			    "psSetProviderData:error(%d)", ret);
54187836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
54197836SJohn.Forte@Sun.COM 			break;
54207836SJohn.Forte@Sun.COM 	}
54217836SJohn.Forte@Sun.COM 
54227836SJohn.Forte@Sun.COM done:
54237836SJohn.Forte@Sun.COM 	return (ret);
54247836SJohn.Forte@Sun.COM }
54257836SJohn.Forte@Sun.COM 
54267836SJohn.Forte@Sun.COM /*
54279585STim.Szeto@Sun.COM  * getProviderData
54289585STim.Szeto@Sun.COM  *
54299585STim.Szeto@Sun.COM  * Purpose: set the provider data from stmf
54309585STim.Szeto@Sun.COM  *
54319585STim.Szeto@Sun.COM  * providerName - unique name of provider
54329585STim.Szeto@Sun.COM  * nvl - nvlist to load/retrieve
54339585STim.Szeto@Sun.COM  * providerType - logical unit or port provider
54349585STim.Szeto@Sun.COM  * setToken - returned stale data token
54359585STim.Szeto@Sun.COM  */
54369585STim.Szeto@Sun.COM int
54379585STim.Szeto@Sun.COM getProviderData(char *providerName, nvlist_t **nvl, int providerType,
54389585STim.Szeto@Sun.COM     uint64_t *setToken)
54399585STim.Szeto@Sun.COM {
54409585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
54419585STim.Szeto@Sun.COM 	int fd;
54429585STim.Szeto@Sun.COM 	int ioctlRet;
54439585STim.Szeto@Sun.COM 	size_t nvlistSize = ALLOC_PP_DATA_SIZE;
54449585STim.Szeto@Sun.COM 	int retryCnt = 0;
54459585STim.Szeto@Sun.COM 	int retryCntMax = MAX_PROVIDER_RETRY;
54469585STim.Szeto@Sun.COM 	stmf_ppioctl_data_t ppi = {0}, *ppi_out = NULL;
54479585STim.Szeto@Sun.COM 	boolean_t retry = B_TRUE;
54489585STim.Szeto@Sun.COM 	stmf_iocdata_t stmfIoctl;
54499585STim.Szeto@Sun.COM 
54509585STim.Szeto@Sun.COM 	if (providerName == NULL) {
54519585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
54529585STim.Szeto@Sun.COM 	}
54539585STim.Szeto@Sun.COM 
54549585STim.Szeto@Sun.COM 	/*
54559585STim.Szeto@Sun.COM 	 * Open control node for stmf
54569585STim.Szeto@Sun.COM 	 */
54579585STim.Szeto@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
54589585STim.Szeto@Sun.COM 		return (ret);
54599585STim.Szeto@Sun.COM 
54609585STim.Szeto@Sun.COM 	/* set provider name and provider type */
54619585STim.Szeto@Sun.COM 	if (strlcpy(ppi.ppi_name, providerName,
54629585STim.Szeto@Sun.COM 	    sizeof (ppi.ppi_name)) >=
54639585STim.Szeto@Sun.COM 	    sizeof (ppi.ppi_name)) {
54649585STim.Szeto@Sun.COM 		ret = STMF_ERROR_INVALID_ARG;
54659585STim.Szeto@Sun.COM 		goto done;
54669585STim.Szeto@Sun.COM 	}
54679585STim.Szeto@Sun.COM 	switch (providerType) {
54689585STim.Szeto@Sun.COM 		case STMF_LU_PROVIDER_TYPE:
54699585STim.Szeto@Sun.COM 			ppi.ppi_lu_provider = 1;
54709585STim.Szeto@Sun.COM 			break;
54719585STim.Szeto@Sun.COM 		case STMF_PORT_PROVIDER_TYPE:
54729585STim.Szeto@Sun.COM 			ppi.ppi_port_provider = 1;
54739585STim.Szeto@Sun.COM 			break;
54749585STim.Szeto@Sun.COM 		default:
54759585STim.Szeto@Sun.COM 			ret = STMF_ERROR_INVALID_ARG;
54769585STim.Szeto@Sun.COM 			goto done;
54779585STim.Szeto@Sun.COM 	}
54789585STim.Szeto@Sun.COM 
54799585STim.Szeto@Sun.COM 	do {
54809585STim.Szeto@Sun.COM 		/* allocate memory for ioctl */
54819585STim.Szeto@Sun.COM 		ppi_out = (stmf_ppioctl_data_t *)calloc(1, nvlistSize +
54829585STim.Szeto@Sun.COM 		    sizeof (stmf_ppioctl_data_t));
54839585STim.Szeto@Sun.COM 		if (ppi_out == NULL) {
54849585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NOMEM;
54859585STim.Szeto@Sun.COM 			goto done;
54869585STim.Szeto@Sun.COM 
54879585STim.Szeto@Sun.COM 		}
54889585STim.Szeto@Sun.COM 
54899585STim.Szeto@Sun.COM 		/* set the size of the ioctl data to allocated buffer */
54909585STim.Szeto@Sun.COM 		ppi.ppi_data_size = nvlistSize;
54919585STim.Szeto@Sun.COM 
54929585STim.Szeto@Sun.COM 		bzero(&stmfIoctl, sizeof (stmfIoctl));
54939585STim.Szeto@Sun.COM 
54949585STim.Szeto@Sun.COM 		stmfIoctl.stmf_version = STMF_VERSION_1;
54959585STim.Szeto@Sun.COM 		stmfIoctl.stmf_ibuf_size = sizeof (stmf_ppioctl_data_t);
54969585STim.Szeto@Sun.COM 		stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ppi;
54979585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf_size = sizeof (stmf_ppioctl_data_t) +
54989585STim.Szeto@Sun.COM 		    nvlistSize;
54999585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)ppi_out;
55009585STim.Szeto@Sun.COM 		ioctlRet = ioctl(fd, STMF_IOCTL_GET_PP_DATA, &stmfIoctl);
55019585STim.Szeto@Sun.COM 		if (ioctlRet != 0) {
55029585STim.Szeto@Sun.COM 			switch (errno) {
55039585STim.Szeto@Sun.COM 				case EBUSY:
55049585STim.Szeto@Sun.COM 					ret = STMF_ERROR_BUSY;
55059585STim.Szeto@Sun.COM 					break;
55069585STim.Szeto@Sun.COM 				case EPERM:
55079585STim.Szeto@Sun.COM 				case EACCES:
55089585STim.Szeto@Sun.COM 					ret = STMF_ERROR_PERM;
55099585STim.Szeto@Sun.COM 					break;
55109585STim.Szeto@Sun.COM 				case EINVAL:
55119585STim.Szeto@Sun.COM 					if (stmfIoctl.stmf_error ==
55129585STim.Szeto@Sun.COM 					    STMF_IOCERR_INSUFFICIENT_BUF) {
55139585STim.Szeto@Sun.COM 						nvlistSize =
55149585STim.Szeto@Sun.COM 						    ppi_out->ppi_data_size;
55159585STim.Szeto@Sun.COM 						free(ppi_out);
55169585STim.Szeto@Sun.COM 						ppi_out = NULL;
55179585STim.Szeto@Sun.COM 						if (retryCnt++ > retryCntMax) {
55189585STim.Szeto@Sun.COM 							retry = B_FALSE;
55199585STim.Szeto@Sun.COM 							ret = STMF_ERROR_BUSY;
55209585STim.Szeto@Sun.COM 						} else {
55219585STim.Szeto@Sun.COM 							ret =
55229585STim.Szeto@Sun.COM 							    STMF_STATUS_SUCCESS;
55239585STim.Szeto@Sun.COM 						}
55249585STim.Szeto@Sun.COM 					} else {
55259585STim.Szeto@Sun.COM 						syslog(LOG_DEBUG,
55269585STim.Szeto@Sun.COM 						    "getProviderData:ioctl"
55279585STim.Szeto@Sun.COM 						    "unable to retrieve "
55289585STim.Szeto@Sun.COM 						    "nvlist");
55299585STim.Szeto@Sun.COM 						ret = STMF_STATUS_ERROR;
55309585STim.Szeto@Sun.COM 					}
55319585STim.Szeto@Sun.COM 					break;
55329585STim.Szeto@Sun.COM 				case ENOENT:
55339585STim.Szeto@Sun.COM 					ret = STMF_ERROR_NOT_FOUND;
55349585STim.Szeto@Sun.COM 					break;
55359585STim.Szeto@Sun.COM 				default:
55369585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
55379585STim.Szeto@Sun.COM 					    "getProviderData:ioctl errno(%d)",
55389585STim.Szeto@Sun.COM 					    errno);
55399585STim.Szeto@Sun.COM 					ret = STMF_STATUS_ERROR;
55409585STim.Szeto@Sun.COM 					break;
55419585STim.Szeto@Sun.COM 			}
55429585STim.Szeto@Sun.COM 			if (ret != STMF_STATUS_SUCCESS)
55439585STim.Szeto@Sun.COM 				goto done;
55449585STim.Szeto@Sun.COM 		}
55459585STim.Szeto@Sun.COM 	} while (retry && stmfIoctl.stmf_error == STMF_IOCERR_INSUFFICIENT_BUF);
55469585STim.Szeto@Sun.COM 
55479585STim.Szeto@Sun.COM 	if ((ret = nvlist_unpack((char *)ppi_out->ppi_data,
55489585STim.Szeto@Sun.COM 	    ppi_out->ppi_data_size, nvl, 0)) != 0) {
55499585STim.Szeto@Sun.COM 		ret = STMF_STATUS_ERROR;
55509585STim.Szeto@Sun.COM 		goto done;
55519585STim.Szeto@Sun.COM 	}
55529585STim.Szeto@Sun.COM 
55539585STim.Szeto@Sun.COM 	/* caller has asked for new token */
55549585STim.Szeto@Sun.COM 	if (setToken) {
55559585STim.Szeto@Sun.COM 		*setToken = ppi_out->ppi_token;
55569585STim.Szeto@Sun.COM 	}
55579585STim.Szeto@Sun.COM done:
55589585STim.Szeto@Sun.COM 	free(ppi_out);
55599585STim.Szeto@Sun.COM 	(void) close(fd);
55609585STim.Szeto@Sun.COM 	return (ret);
55619585STim.Szeto@Sun.COM }
55629585STim.Szeto@Sun.COM 
55639585STim.Szeto@Sun.COM /*
55647836SJohn.Forte@Sun.COM  * setProviderData
55657836SJohn.Forte@Sun.COM  *
55669585STim.Szeto@Sun.COM  * Purpose: set the provider data in stmf
55677836SJohn.Forte@Sun.COM  *
55687836SJohn.Forte@Sun.COM  * providerName - unique name of provider
55697836SJohn.Forte@Sun.COM  * nvl - nvlist to set
55707836SJohn.Forte@Sun.COM  * providerType - logical unit or port provider
55719585STim.Szeto@Sun.COM  * setToken - stale data token to check if not NULL
55727836SJohn.Forte@Sun.COM  */
55737836SJohn.Forte@Sun.COM static int
55749585STim.Szeto@Sun.COM setProviderData(int fd, char *providerName, nvlist_t *nvl, int providerType,
55759585STim.Szeto@Sun.COM     uint64_t *setToken)
55767836SJohn.Forte@Sun.COM {
55777836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
55787836SJohn.Forte@Sun.COM 	int ioctlRet;
55797836SJohn.Forte@Sun.COM 	size_t nvlistEncodedSize;
55807836SJohn.Forte@Sun.COM 	stmf_ppioctl_data_t *ppi = NULL;
55819585STim.Szeto@Sun.COM 	uint64_t outToken;
55827836SJohn.Forte@Sun.COM 	char *allocatedNvBuffer;
55837836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
55847836SJohn.Forte@Sun.COM 
55857836SJohn.Forte@Sun.COM 	if (providerName == NULL) {
55867836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
55877836SJohn.Forte@Sun.COM 	}
55887836SJohn.Forte@Sun.COM 
55897836SJohn.Forte@Sun.COM 	/* get size of encoded nvlist */
55907836SJohn.Forte@Sun.COM 	if (nvlist_size(nvl, &nvlistEncodedSize, NV_ENCODE_XDR) != 0) {
55917836SJohn.Forte@Sun.COM 		return (STMF_STATUS_ERROR);
55927836SJohn.Forte@Sun.COM 	}
55937836SJohn.Forte@Sun.COM 
55947836SJohn.Forte@Sun.COM 	/* allocate memory for ioctl */
55957836SJohn.Forte@Sun.COM 	ppi = (stmf_ppioctl_data_t *)calloc(1, nvlistEncodedSize +
55967836SJohn.Forte@Sun.COM 	    sizeof (stmf_ppioctl_data_t));
55977836SJohn.Forte@Sun.COM 	if (ppi == NULL) {
55987836SJohn.Forte@Sun.COM 		return (STMF_ERROR_NOMEM);
55997836SJohn.Forte@Sun.COM 	}
56007836SJohn.Forte@Sun.COM 
56019585STim.Szeto@Sun.COM 	if (setToken) {
56029585STim.Szeto@Sun.COM 		ppi->ppi_token_valid = 1;
56039585STim.Szeto@Sun.COM 		ppi->ppi_token = *setToken;
56049585STim.Szeto@Sun.COM 	}
56059585STim.Szeto@Sun.COM 
56067836SJohn.Forte@Sun.COM 	allocatedNvBuffer = (char *)&ppi->ppi_data;
56077836SJohn.Forte@Sun.COM 	if (nvlist_pack(nvl, &allocatedNvBuffer, &nvlistEncodedSize,
56087836SJohn.Forte@Sun.COM 	    NV_ENCODE_XDR, 0) != 0) {
56097836SJohn.Forte@Sun.COM 		return (STMF_STATUS_ERROR);
56107836SJohn.Forte@Sun.COM 	}
56117836SJohn.Forte@Sun.COM 
56127836SJohn.Forte@Sun.COM 	/* set provider name and provider type */
56137836SJohn.Forte@Sun.COM 	(void) strncpy(ppi->ppi_name, providerName, sizeof (ppi->ppi_name));
56147836SJohn.Forte@Sun.COM 	switch (providerType) {
56157836SJohn.Forte@Sun.COM 		case STMF_LU_PROVIDER_TYPE:
56167836SJohn.Forte@Sun.COM 			ppi->ppi_lu_provider = 1;
56177836SJohn.Forte@Sun.COM 			break;
56187836SJohn.Forte@Sun.COM 		case STMF_PORT_PROVIDER_TYPE:
56197836SJohn.Forte@Sun.COM 			ppi->ppi_port_provider = 1;
56207836SJohn.Forte@Sun.COM 			break;
56217836SJohn.Forte@Sun.COM 		default:
56227836SJohn.Forte@Sun.COM 			return (STMF_ERROR_INVALID_ARG);
56237836SJohn.Forte@Sun.COM 	}
56247836SJohn.Forte@Sun.COM 
56257836SJohn.Forte@Sun.COM 	/* set the size of the ioctl data to packed data size */
56267836SJohn.Forte@Sun.COM 	ppi->ppi_data_size = nvlistEncodedSize;
56277836SJohn.Forte@Sun.COM 
56287836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
56297836SJohn.Forte@Sun.COM 
56307836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
56317836SJohn.Forte@Sun.COM 	/*
56327836SJohn.Forte@Sun.COM 	 * Subtracting 8 from the size as that is the size of the last member
56337836SJohn.Forte@Sun.COM 	 * of the structure where the packed data resides
56347836SJohn.Forte@Sun.COM 	 */
56357836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = nvlistEncodedSize +
56367836SJohn.Forte@Sun.COM 	    sizeof (stmf_ppioctl_data_t) - 8;
56377836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)ppi;
56389585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf_size = sizeof (uint64_t);
56399585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&outToken;
56407836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_LOAD_PP_DATA, &stmfIoctl);
56417836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
56427836SJohn.Forte@Sun.COM 		switch (errno) {
56437836SJohn.Forte@Sun.COM 			case EBUSY:
56447836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
56457836SJohn.Forte@Sun.COM 				break;
56469585STim.Szeto@Sun.COM 			case EPERM:
56477836SJohn.Forte@Sun.COM 			case EACCES:
56487836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
56497836SJohn.Forte@Sun.COM 				break;
56509585STim.Szeto@Sun.COM 			case EINVAL:
56519585STim.Szeto@Sun.COM 				if (stmfIoctl.stmf_error ==
56529585STim.Szeto@Sun.COM 				    STMF_IOCERR_PPD_UPDATED) {
56539585STim.Szeto@Sun.COM 					ret = STMF_ERROR_PROV_DATA_STALE;
56549585STim.Szeto@Sun.COM 				} else {
56559585STim.Szeto@Sun.COM 					ret = STMF_STATUS_ERROR;
56569585STim.Szeto@Sun.COM 				}
56579585STim.Szeto@Sun.COM 				break;
56587836SJohn.Forte@Sun.COM 			default:
56597836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
56607836SJohn.Forte@Sun.COM 				    "setProviderData:ioctl errno(%d)", errno);
56617836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
56627836SJohn.Forte@Sun.COM 				break;
56637836SJohn.Forte@Sun.COM 		}
56647836SJohn.Forte@Sun.COM 		if (ret != STMF_STATUS_SUCCESS)
56657836SJohn.Forte@Sun.COM 			goto done;
56667836SJohn.Forte@Sun.COM 	}
56677836SJohn.Forte@Sun.COM 
56689585STim.Szeto@Sun.COM 	/* caller has asked for new token */
56699585STim.Szeto@Sun.COM 	if (setToken) {
56709585STim.Szeto@Sun.COM 		*setToken = outToken;
56719585STim.Szeto@Sun.COM 	}
56727836SJohn.Forte@Sun.COM done:
56737836SJohn.Forte@Sun.COM 	free(ppi);
56747836SJohn.Forte@Sun.COM 	return (ret);
56757836SJohn.Forte@Sun.COM }
56769585STim.Szeto@Sun.COM 
56779585STim.Szeto@Sun.COM /*
56789585STim.Szeto@Sun.COM  * set the persistence method in the library only or library and service
56799585STim.Szeto@Sun.COM  */
56809585STim.Szeto@Sun.COM int
56819585STim.Szeto@Sun.COM stmfSetPersistMethod(uint8_t persistType, boolean_t serviceSet)
56829585STim.Szeto@Sun.COM {
56839585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
56849585STim.Szeto@Sun.COM 	int oldPersist;
56859585STim.Szeto@Sun.COM 
56869585STim.Szeto@Sun.COM 	(void) pthread_mutex_lock(&persistenceTypeLock);
56879585STim.Szeto@Sun.COM 	oldPersist = iPersistType;
56889585STim.Szeto@Sun.COM 	if (persistType == STMF_PERSIST_NONE ||
56899585STim.Szeto@Sun.COM 	    persistType == STMF_PERSIST_SMF) {
56909585STim.Szeto@Sun.COM 		iLibSetPersist = B_TRUE;
56919585STim.Szeto@Sun.COM 		iPersistType = persistType;
56929585STim.Szeto@Sun.COM 	} else {
56939585STim.Szeto@Sun.COM 		(void) pthread_mutex_unlock(&persistenceTypeLock);
56949585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
56959585STim.Szeto@Sun.COM 	}
56969585STim.Szeto@Sun.COM 	/* Is this for this library open or in SMF */
56979585STim.Szeto@Sun.COM 	if (serviceSet == B_TRUE) {
56989585STim.Szeto@Sun.COM 		ret = psSetServicePersist(persistType);
56999585STim.Szeto@Sun.COM 		if (ret != STMF_PS_SUCCESS) {
57009585STim.Szeto@Sun.COM 			ret = STMF_ERROR_PERSIST_TYPE;
57019585STim.Szeto@Sun.COM 			/* Set to old value */
57029585STim.Szeto@Sun.COM 			iPersistType = oldPersist;
57039585STim.Szeto@Sun.COM 		}
57049585STim.Szeto@Sun.COM 	}
57059585STim.Szeto@Sun.COM 	(void) pthread_mutex_unlock(&persistenceTypeLock);
57069585STim.Szeto@Sun.COM 
57079585STim.Szeto@Sun.COM 	return (ret);
57089585STim.Szeto@Sun.COM }
57099585STim.Szeto@Sun.COM 
57109585STim.Szeto@Sun.COM /*
57119585STim.Szeto@Sun.COM  * Only returns internal state for persist. If unset, goes to ps. If that
57129585STim.Szeto@Sun.COM  * fails, returns default setting
57139585STim.Szeto@Sun.COM  */
57149585STim.Szeto@Sun.COM static uint8_t
57159585STim.Szeto@Sun.COM iGetPersistMethod()
57169585STim.Szeto@Sun.COM {
57179585STim.Szeto@Sun.COM 
57189585STim.Szeto@Sun.COM 	uint8_t persistType = 0;
57199585STim.Szeto@Sun.COM 
57209585STim.Szeto@Sun.COM 	(void) pthread_mutex_lock(&persistenceTypeLock);
57219585STim.Szeto@Sun.COM 	if (iLibSetPersist) {
57229585STim.Szeto@Sun.COM 		persistType = iPersistType;
57239585STim.Szeto@Sun.COM 	} else {
57249585STim.Szeto@Sun.COM 		int ret;
57259585STim.Szeto@Sun.COM 		ret = psGetServicePersist(&persistType);
57269585STim.Szeto@Sun.COM 		if (ret != STMF_PS_SUCCESS) {
57279585STim.Szeto@Sun.COM 			/* set to default */
57289585STim.Szeto@Sun.COM 			persistType = STMF_DEFAULT_PERSIST;
57299585STim.Szeto@Sun.COM 		}
57309585STim.Szeto@Sun.COM 	}
57319585STim.Szeto@Sun.COM 	(void) pthread_mutex_unlock(&persistenceTypeLock);
57329585STim.Szeto@Sun.COM 	return (persistType);
57339585STim.Szeto@Sun.COM }
57349585STim.Szeto@Sun.COM 
57359585STim.Szeto@Sun.COM /*
57369585STim.Szeto@Sun.COM  * Returns either library state or persistent config state depending on
57379585STim.Szeto@Sun.COM  * serviceState
57389585STim.Szeto@Sun.COM  */
57399585STim.Szeto@Sun.COM int
57409585STim.Szeto@Sun.COM stmfGetPersistMethod(uint8_t *persistType, boolean_t serviceState)
57419585STim.Szeto@Sun.COM {
57429585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
57439585STim.Szeto@Sun.COM 
57449585STim.Szeto@Sun.COM 	if (persistType == NULL) {
57459585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
57469585STim.Szeto@Sun.COM 	}
57479585STim.Szeto@Sun.COM 	if (serviceState) {
57489585STim.Szeto@Sun.COM 		ret = psGetServicePersist(persistType);
57499585STim.Szeto@Sun.COM 		if (ret != STMF_PS_SUCCESS) {
57509585STim.Szeto@Sun.COM 			ret = STMF_ERROR_PERSIST_TYPE;
57519585STim.Szeto@Sun.COM 		}
57529585STim.Szeto@Sun.COM 	} else {
57539585STim.Szeto@Sun.COM 		(void) pthread_mutex_lock(&persistenceTypeLock);
57549585STim.Szeto@Sun.COM 		if (iLibSetPersist) {
57559585STim.Szeto@Sun.COM 			*persistType = iPersistType;
57569585STim.Szeto@Sun.COM 		} else {
57579585STim.Szeto@Sun.COM 			*persistType = STMF_DEFAULT_PERSIST;
57589585STim.Szeto@Sun.COM 		}
57599585STim.Szeto@Sun.COM 		(void) pthread_mutex_unlock(&persistenceTypeLock);
57609585STim.Szeto@Sun.COM 	}
57619585STim.Szeto@Sun.COM 
57629585STim.Szeto@Sun.COM 	return (ret);
57639585STim.Szeto@Sun.COM }
5764