xref: /onnv-gate/usr/src/lib/libstmf/common/stmf.c (revision 11691)
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 /*
22*11691SSrivijitha.Dugganapalli@Sun.COM  * Copyright 2010 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>
5010725SJohn.Forte@Sun.COM #include <sys/pppt_ioctl.h>
5111103SJohn.Forte@Sun.COM #include <macros.h>
527836SJohn.Forte@Sun.COM 
537836SJohn.Forte@Sun.COM #define	STMF_PATH    "/devices/pseudo/stmf@0:admin"
549585STim.Szeto@Sun.COM #define	SBD_PATH    "/devices/pseudo/stmf_sbd@0:admin"
5510725SJohn.Forte@Sun.COM #define	PPPT_PATH    "/devices/pseudo/pppt@0:pppt"
567836SJohn.Forte@Sun.COM 
577836SJohn.Forte@Sun.COM #define	EUI "eui."
587836SJohn.Forte@Sun.COM #define	WWN "wwn."
597836SJohn.Forte@Sun.COM #define	IQN "iqn."
609585STim.Szeto@Sun.COM #define	LU_ASCII_GUID_SIZE 32
619585STim.Szeto@Sun.COM #define	LU_GUID_SIZE 16
629585STim.Szeto@Sun.COM #define	OUI_ASCII_SIZE 6
6310765SJohn.Forte@Sun.COM #define	HOST_ID_ASCII_SIZE 8
649585STim.Szeto@Sun.COM #define	OUI_SIZE 3
6510765SJohn.Forte@Sun.COM #define	HOST_ID_SIZE 4
667836SJohn.Forte@Sun.COM #define	IDENT_LENGTH_BYTE 3
677836SJohn.Forte@Sun.COM 
689585STim.Szeto@Sun.COM /* various initial allocation values */
699585STim.Szeto@Sun.COM #define	ALLOC_LU		8192
709585STim.Szeto@Sun.COM #define	ALLOC_TARGET_PORT	2048
719585STim.Szeto@Sun.COM #define	ALLOC_PROVIDER		64
729585STim.Szeto@Sun.COM #define	ALLOC_GROUP		2048
739585STim.Szeto@Sun.COM #define	ALLOC_SESSION		2048
749585STim.Szeto@Sun.COM #define	ALLOC_VE		256
759585STim.Szeto@Sun.COM #define	ALLOC_PP_DATA_SIZE	128*1024
769585STim.Szeto@Sun.COM #define	ALLOC_GRP_MEMBER	256
779585STim.Szeto@Sun.COM 
787836SJohn.Forte@Sun.COM #define	MAX_ISCSI_NAME	223
799585STim.Szeto@Sun.COM #define	MAX_SERIAL_SIZE 252 + 1
809585STim.Szeto@Sun.COM #define	MAX_LU_ALIAS_SIZE 256
819585STim.Szeto@Sun.COM #define	MAX_SBD_PROPS	MAXPATHLEN + MAX_SERIAL_SIZE + MAX_LU_ALIAS_SIZE
827836SJohn.Forte@Sun.COM 
837836SJohn.Forte@Sun.COM #define	OPEN_STMF 0
847836SJohn.Forte@Sun.COM #define	OPEN_EXCL_STMF O_EXCL
857836SJohn.Forte@Sun.COM 
869585STim.Szeto@Sun.COM #define	OPEN_SBD 0
879585STim.Szeto@Sun.COM #define	OPEN_EXCL_SBD O_EXCL
889585STim.Szeto@Sun.COM 
8910725SJohn.Forte@Sun.COM #define	OPEN_PPPT 0
9010725SJohn.Forte@Sun.COM #define	OPEN_EXCL_PPPT O_EXCL
9110725SJohn.Forte@Sun.COM 
927836SJohn.Forte@Sun.COM #define	LOGICAL_UNIT_TYPE 0
937836SJohn.Forte@Sun.COM #define	TARGET_TYPE 1
947836SJohn.Forte@Sun.COM #define	STMF_SERVICE_TYPE 2
957836SJohn.Forte@Sun.COM 
969585STim.Szeto@Sun.COM #define	HOST_GROUP   1
979585STim.Szeto@Sun.COM #define	TARGET_GROUP 2
989585STim.Szeto@Sun.COM 
999585STim.Szeto@Sun.COM /* set default persistence here */
1009585STim.Szeto@Sun.COM #define	STMF_DEFAULT_PERSIST	STMF_PERSIST_SMF
1019585STim.Szeto@Sun.COM 
1029585STim.Szeto@Sun.COM #define	MAX_PROVIDER_RETRY 30
1039585STim.Szeto@Sun.COM 
1047836SJohn.Forte@Sun.COM static int openStmf(int, int *fd);
1059585STim.Szeto@Sun.COM static int openSbd(int, int *fd);
10610725SJohn.Forte@Sun.COM static int openPppt(int, int *fd);
1077836SJohn.Forte@Sun.COM static int groupIoctl(int fd, int cmd, stmfGroupName *);
1087836SJohn.Forte@Sun.COM static int loadStore(int fd);
1097836SJohn.Forte@Sun.COM static int initializeConfig();
1107836SJohn.Forte@Sun.COM static int groupMemberIoctl(int fd, int cmd, stmfGroupName *, stmfDevid *);
1117836SJohn.Forte@Sun.COM static int guidCompare(const void *, const void *);
1127836SJohn.Forte@Sun.COM static int addViewEntryIoctl(int fd, stmfGuid *, stmfViewEntry *);
1137836SJohn.Forte@Sun.COM static int loadHostGroups(int fd, stmfGroupList *);
1147836SJohn.Forte@Sun.COM static int loadTargetGroups(int fd, stmfGroupList *);
1157836SJohn.Forte@Sun.COM static int getStmfState(stmf_state_desc_t *);
1167836SJohn.Forte@Sun.COM static int setStmfState(int fd, stmf_state_desc_t *, int);
1179585STim.Szeto@Sun.COM static int setProviderData(int fd, char *, nvlist_t *, int, uint64_t *);
1189585STim.Szeto@Sun.COM static int createDiskResource(luResourceImpl *);
1199585STim.Szeto@Sun.COM static int createDiskLu(diskResource *, stmfGuid *);
1209585STim.Szeto@Sun.COM static int deleteDiskLu(stmfGuid *luGuid);
1219585STim.Szeto@Sun.COM static int getDiskProp(luResourceImpl *, uint32_t, char *, size_t *);
1229585STim.Szeto@Sun.COM static int getDiskAllProps(stmfGuid *luGuid, luResource *hdl);
1239585STim.Szeto@Sun.COM static int loadDiskPropsFromDriver(luResourceImpl *, sbd_lu_props_t *);
1249585STim.Szeto@Sun.COM static int removeGuidFromDiskStore(stmfGuid *);
1259585STim.Szeto@Sun.COM static int addGuidToDiskStore(stmfGuid *, char *);
1269585STim.Szeto@Sun.COM static int persistDiskGuid(stmfGuid *, char *, boolean_t);
1279585STim.Szeto@Sun.COM static int setDiskProp(luResourceImpl *, uint32_t, const char *);
12811103SJohn.Forte@Sun.COM static int getDiskGlobalProp(uint32_t prop, char *propVal, size_t *propLen);
1299585STim.Szeto@Sun.COM static int checkHexUpper(char *);
1309585STim.Szeto@Sun.COM static int strToShift(const char *);
1319585STim.Szeto@Sun.COM static int niceStrToNum(const char *, uint64_t *);
1329585STim.Szeto@Sun.COM static void diskError(uint32_t, int *);
1339585STim.Szeto@Sun.COM static int importDiskLu(char *fname, stmfGuid *);
1349585STim.Szeto@Sun.COM static int modifyDiskLu(diskResource *, stmfGuid *, const char *);
1359585STim.Szeto@Sun.COM static int modifyDiskLuProp(stmfGuid *, const char *, uint32_t, const char *);
1369585STim.Szeto@Sun.COM static int validateModifyDiskProp(uint32_t);
1379585STim.Szeto@Sun.COM static uint8_t iGetPersistMethod();
1389585STim.Szeto@Sun.COM static int groupListIoctl(stmfGroupList **, int);
1399585STim.Szeto@Sun.COM static int iLoadGroupFromPs(stmfGroupList **, int);
1409585STim.Szeto@Sun.COM static int groupMemberListIoctl(stmfGroupName *, stmfGroupProperties **, int);
1419585STim.Szeto@Sun.COM static int getProviderData(char *, nvlist_t **, int, uint64_t *);
14210725SJohn.Forte@Sun.COM static int setDiskStandby(stmfGuid *luGuid);
14311103SJohn.Forte@Sun.COM static int setDiskGlobalProp(uint32_t, const char *);
1449585STim.Szeto@Sun.COM static int viewEntryCompare(const void *, const void *);
14510725SJohn.Forte@Sun.COM static void deleteNonActiveLus();
1469585STim.Szeto@Sun.COM 
1479585STim.Szeto@Sun.COM static pthread_mutex_t persistenceTypeLock = PTHREAD_MUTEX_INITIALIZER;
1489585STim.Szeto@Sun.COM static int iPersistType = 0;
1499585STim.Szeto@Sun.COM /* when B_TRUE, no need to access SMF anymore. Just use iPersistType */
1509585STim.Szeto@Sun.COM static boolean_t iLibSetPersist = B_FALSE;
1517836SJohn.Forte@Sun.COM 
1527836SJohn.Forte@Sun.COM /*
1537836SJohn.Forte@Sun.COM  * Open for stmf module
1547836SJohn.Forte@Sun.COM  *
1557836SJohn.Forte@Sun.COM  * flag - open flag (OPEN_STMF, OPEN_EXCL_STMF)
1567836SJohn.Forte@Sun.COM  * fd - pointer to integer. On success, contains the stmf file descriptor
1577836SJohn.Forte@Sun.COM  */
1587836SJohn.Forte@Sun.COM static int
1597836SJohn.Forte@Sun.COM openStmf(int flag, int *fd)
1607836SJohn.Forte@Sun.COM {
1617836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_ERROR;
1627836SJohn.Forte@Sun.COM 
1637836SJohn.Forte@Sun.COM 	if ((*fd = open(STMF_PATH, O_NDELAY | O_RDONLY | flag)) != -1) {
1647836SJohn.Forte@Sun.COM 		ret = STMF_STATUS_SUCCESS;
1657836SJohn.Forte@Sun.COM 	} else {
1667836SJohn.Forte@Sun.COM 		if (errno == EBUSY) {
1677836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
1689585STim.Szeto@Sun.COM 		} else if (errno == EACCES) {
1699585STim.Szeto@Sun.COM 			ret = STMF_ERROR_PERM;
1707836SJohn.Forte@Sun.COM 		} else {
1717836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
1727836SJohn.Forte@Sun.COM 		}
1737836SJohn.Forte@Sun.COM 		syslog(LOG_DEBUG, "openStmf:open failure:%s:errno(%d)",
1747836SJohn.Forte@Sun.COM 		    STMF_PATH, errno);
1757836SJohn.Forte@Sun.COM 	}
1767836SJohn.Forte@Sun.COM 
1777836SJohn.Forte@Sun.COM 	return (ret);
1787836SJohn.Forte@Sun.COM }
1797836SJohn.Forte@Sun.COM 
1807836SJohn.Forte@Sun.COM /*
1819585STim.Szeto@Sun.COM  * Open for sbd module
1829585STim.Szeto@Sun.COM  *
18310725SJohn.Forte@Sun.COM  * flag - open flag (OPEN_SBD, OPEN_EXCL_SBD)
1849585STim.Szeto@Sun.COM  * fd - pointer to integer. On success, contains the stmf file descriptor
1859585STim.Szeto@Sun.COM  */
1869585STim.Szeto@Sun.COM static int
1879585STim.Szeto@Sun.COM openSbd(int flag, int *fd)
1889585STim.Szeto@Sun.COM {
1899585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_ERROR;
1909585STim.Szeto@Sun.COM 
1919585STim.Szeto@Sun.COM 	if ((*fd = open(SBD_PATH, O_NDELAY | O_RDONLY | flag)) != -1) {
1929585STim.Szeto@Sun.COM 		ret = STMF_STATUS_SUCCESS;
1939585STim.Szeto@Sun.COM 	} else {
1949585STim.Szeto@Sun.COM 		if (errno == EBUSY) {
1959585STim.Szeto@Sun.COM 			ret = STMF_ERROR_BUSY;
1969585STim.Szeto@Sun.COM 		} else if (errno == EACCES) {
1979585STim.Szeto@Sun.COM 			ret = STMF_ERROR_PERM;
1989585STim.Szeto@Sun.COM 		} else {
1999585STim.Szeto@Sun.COM 			ret = STMF_STATUS_ERROR;
2009585STim.Szeto@Sun.COM 		}
2019585STim.Szeto@Sun.COM 		syslog(LOG_DEBUG, "openSbd:open failure:%s:errno(%d)",
2029585STim.Szeto@Sun.COM 		    SBD_PATH, errno);
2039585STim.Szeto@Sun.COM 	}
2049585STim.Szeto@Sun.COM 
2059585STim.Szeto@Sun.COM 	return (ret);
2069585STim.Szeto@Sun.COM }
2079585STim.Szeto@Sun.COM 
2089585STim.Szeto@Sun.COM /*
20910725SJohn.Forte@Sun.COM  * Open for pppt module
21010725SJohn.Forte@Sun.COM  *
21110725SJohn.Forte@Sun.COM  * flag - open flag (OPEN_PPPT, OPEN_EXCL_PPPT)
21210725SJohn.Forte@Sun.COM  * fd - pointer to integer. On success, contains the stmf file descriptor
21310725SJohn.Forte@Sun.COM  */
21410725SJohn.Forte@Sun.COM static int
21510725SJohn.Forte@Sun.COM openPppt(int flag, int *fd)
21610725SJohn.Forte@Sun.COM {
21710725SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_ERROR;
21810725SJohn.Forte@Sun.COM 
21910725SJohn.Forte@Sun.COM 	if ((*fd = open(PPPT_PATH, O_RDONLY | flag)) != -1) {
22010725SJohn.Forte@Sun.COM 		ret = STMF_STATUS_SUCCESS;
22110725SJohn.Forte@Sun.COM 	} else {
22210725SJohn.Forte@Sun.COM 		if (errno == EBUSY) {
22310725SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
22410725SJohn.Forte@Sun.COM 		} else if (errno == EACCES) {
22510725SJohn.Forte@Sun.COM 			ret = STMF_ERROR_PERM;
22610725SJohn.Forte@Sun.COM 		} else {
22710725SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
22810725SJohn.Forte@Sun.COM 		}
22910725SJohn.Forte@Sun.COM 		syslog(LOG_DEBUG, "openPppt:open failure:%s:errno(%d)",
23010725SJohn.Forte@Sun.COM 		    PPPT_PATH, errno);
23110725SJohn.Forte@Sun.COM 	}
23210725SJohn.Forte@Sun.COM 
23310725SJohn.Forte@Sun.COM 	return (ret);
23410725SJohn.Forte@Sun.COM }
23510725SJohn.Forte@Sun.COM 
23610725SJohn.Forte@Sun.COM /*
2377836SJohn.Forte@Sun.COM  * initializeConfig
2387836SJohn.Forte@Sun.COM  *
2397836SJohn.Forte@Sun.COM  * This routine should be called before any ioctl requiring initialization
2407836SJohn.Forte@Sun.COM  * which is basically everything except stmfGetState(), setStmfState() and
2417836SJohn.Forte@Sun.COM  * stmfLoadConfig().
2427836SJohn.Forte@Sun.COM  */
2437836SJohn.Forte@Sun.COM static int
2447836SJohn.Forte@Sun.COM initializeConfig()
2457836SJohn.Forte@Sun.COM {
2467836SJohn.Forte@Sun.COM 	int ret;
2477836SJohn.Forte@Sun.COM 	stmfState state;
2487836SJohn.Forte@Sun.COM 
2497836SJohn.Forte@Sun.COM 
2507836SJohn.Forte@Sun.COM 	ret = stmfGetState(&state);
2517836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
2527836SJohn.Forte@Sun.COM 		return (ret);
2537836SJohn.Forte@Sun.COM 	}
2547836SJohn.Forte@Sun.COM 
2557836SJohn.Forte@Sun.COM 	/* if we've already initialized or in the process, return success */
2567836SJohn.Forte@Sun.COM 	if (state.configState == STMF_CONFIG_STATE_INIT_DONE ||
2577836SJohn.Forte@Sun.COM 	    state.configState == STMF_CONFIG_STATE_INIT) {
2587836SJohn.Forte@Sun.COM 		return (STMF_STATUS_SUCCESS);
2597836SJohn.Forte@Sun.COM 	}
2607836SJohn.Forte@Sun.COM 
2617836SJohn.Forte@Sun.COM 	ret = stmfLoadConfig();
2627836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
2637836SJohn.Forte@Sun.COM 		syslog(LOG_DEBUG,
2647836SJohn.Forte@Sun.COM 		    "initializeConfig:stmfLoadConfig:error(%d)", ret);
2657836SJohn.Forte@Sun.COM 		return (ret);
2667836SJohn.Forte@Sun.COM 	}
2677836SJohn.Forte@Sun.COM 
2687836SJohn.Forte@Sun.COM 	ret = stmfGetState(&state);
2697836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
2707836SJohn.Forte@Sun.COM 		syslog(LOG_DEBUG,
2717836SJohn.Forte@Sun.COM 		    "initializeConfig:stmfGetState:error(%d)", ret);
2727836SJohn.Forte@Sun.COM 		return (ret);
2737836SJohn.Forte@Sun.COM 	}
2747836SJohn.Forte@Sun.COM 
2757836SJohn.Forte@Sun.COM 	if (state.configState != STMF_CONFIG_STATE_INIT_DONE) {
2767836SJohn.Forte@Sun.COM 		syslog(LOG_DEBUG, "initializeConfig:state.configState(%d)",
2777836SJohn.Forte@Sun.COM 		    state.configState);
2787836SJohn.Forte@Sun.COM 		ret = STMF_STATUS_ERROR;
2797836SJohn.Forte@Sun.COM 	}
2807836SJohn.Forte@Sun.COM 
2817836SJohn.Forte@Sun.COM 	return (ret);
2827836SJohn.Forte@Sun.COM }
2837836SJohn.Forte@Sun.COM 
2847836SJohn.Forte@Sun.COM 
2857836SJohn.Forte@Sun.COM /*
2867836SJohn.Forte@Sun.COM  * groupIoctl
2877836SJohn.Forte@Sun.COM  *
2887836SJohn.Forte@Sun.COM  * Purpose: issue ioctl for create/delete on group
2897836SJohn.Forte@Sun.COM  *
2907836SJohn.Forte@Sun.COM  * cmd - valid STMF ioctl group cmd
2917836SJohn.Forte@Sun.COM  * groupName - groupName to create or delete
2927836SJohn.Forte@Sun.COM  */
2937836SJohn.Forte@Sun.COM static int
2947836SJohn.Forte@Sun.COM groupIoctl(int fd, int cmd, stmfGroupName *groupName)
2957836SJohn.Forte@Sun.COM {
2967836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
2977836SJohn.Forte@Sun.COM 	int ioctlRet;
2987836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
2997836SJohn.Forte@Sun.COM 	stmf_group_name_t iGroupName;
3007836SJohn.Forte@Sun.COM 
3017836SJohn.Forte@Sun.COM 	bzero(&iGroupName, sizeof (iGroupName));
3027836SJohn.Forte@Sun.COM 
3037836SJohn.Forte@Sun.COM 	bcopy(groupName, &iGroupName.name, strlen((char *)groupName));
3047836SJohn.Forte@Sun.COM 
3057836SJohn.Forte@Sun.COM 	iGroupName.name_size = strlen((char *)groupName);
3067836SJohn.Forte@Sun.COM 
3077836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
3087836SJohn.Forte@Sun.COM 	/*
3097836SJohn.Forte@Sun.COM 	 * Issue ioctl to create the host group
3107836SJohn.Forte@Sun.COM 	 */
3117836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
3127836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (iGroupName);
3137836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&iGroupName;
3147836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
3157836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
3167836SJohn.Forte@Sun.COM 		switch (errno) {
3179585STim.Szeto@Sun.COM 			case EPERM:
3187836SJohn.Forte@Sun.COM 			case EACCES:
3197836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
3207836SJohn.Forte@Sun.COM 				break;
3217836SJohn.Forte@Sun.COM 			default:
3227836SJohn.Forte@Sun.COM 				switch (stmfIoctl.stmf_error) {
3237836SJohn.Forte@Sun.COM 					case STMF_IOCERR_TG_EXISTS:
3247836SJohn.Forte@Sun.COM 					case STMF_IOCERR_HG_EXISTS:
3257836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_EXISTS;
3267836SJohn.Forte@Sun.COM 						break;
3277836SJohn.Forte@Sun.COM 					case STMF_IOCERR_TG_IN_USE:
3287836SJohn.Forte@Sun.COM 					case STMF_IOCERR_HG_IN_USE:
3297836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_GROUP_IN_USE;
3307836SJohn.Forte@Sun.COM 						break;
3317836SJohn.Forte@Sun.COM 					case STMF_IOCERR_INVALID_HG:
3327836SJohn.Forte@Sun.COM 					case STMF_IOCERR_INVALID_TG:
3337836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_NOT_FOUND;
3347836SJohn.Forte@Sun.COM 						break;
3357836SJohn.Forte@Sun.COM 					default:
3367836SJohn.Forte@Sun.COM 						syslog(LOG_DEBUG,
3377836SJohn.Forte@Sun.COM 						    "groupIoctl:error(%d)",
3387836SJohn.Forte@Sun.COM 						    stmfIoctl.stmf_error);
3397836SJohn.Forte@Sun.COM 						ret = STMF_STATUS_ERROR;
3407836SJohn.Forte@Sun.COM 						break;
3417836SJohn.Forte@Sun.COM 				}
3427836SJohn.Forte@Sun.COM 				break;
3437836SJohn.Forte@Sun.COM 		}
3447836SJohn.Forte@Sun.COM 	}
3457836SJohn.Forte@Sun.COM done:
3467836SJohn.Forte@Sun.COM 	return (ret);
3477836SJohn.Forte@Sun.COM }
3487836SJohn.Forte@Sun.COM 
3497836SJohn.Forte@Sun.COM /*
3509585STim.Szeto@Sun.COM  * groupMemberIoctl
3517836SJohn.Forte@Sun.COM  *
3527836SJohn.Forte@Sun.COM  * Purpose: issue ioctl for add/remove member on group
3537836SJohn.Forte@Sun.COM  *
3547836SJohn.Forte@Sun.COM  * cmd - valid STMF ioctl group member cmd
3557836SJohn.Forte@Sun.COM  * groupName - groupName to add to or remove from
3567836SJohn.Forte@Sun.COM  * devid - group member to add or remove
3577836SJohn.Forte@Sun.COM  */
3587836SJohn.Forte@Sun.COM static int
3597836SJohn.Forte@Sun.COM groupMemberIoctl(int fd, int cmd, stmfGroupName *groupName, stmfDevid *devid)
3607836SJohn.Forte@Sun.COM {
3617836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
3627836SJohn.Forte@Sun.COM 	int ioctlRet;
3637836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
3647836SJohn.Forte@Sun.COM 	stmf_group_op_data_t stmfGroupData;
3657836SJohn.Forte@Sun.COM 
3667836SJohn.Forte@Sun.COM 	bzero(&stmfGroupData, sizeof (stmfGroupData));
3677836SJohn.Forte@Sun.COM 
3687836SJohn.Forte@Sun.COM 	bcopy(groupName, &stmfGroupData.group.name, strlen((char *)groupName));
3697836SJohn.Forte@Sun.COM 
3707836SJohn.Forte@Sun.COM 	stmfGroupData.group.name_size = strlen((char *)groupName);
3717836SJohn.Forte@Sun.COM 	stmfGroupData.ident[IDENT_LENGTH_BYTE] = devid->identLength;
3727836SJohn.Forte@Sun.COM 	bcopy(&(devid->ident), &stmfGroupData.ident[IDENT_LENGTH_BYTE + 1],
3737836SJohn.Forte@Sun.COM 	    devid->identLength);
3747836SJohn.Forte@Sun.COM 
3757836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
3767836SJohn.Forte@Sun.COM 	/*
3777836SJohn.Forte@Sun.COM 	 * Issue ioctl to add to the host group
3787836SJohn.Forte@Sun.COM 	 */
3797836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
3807836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (stmfGroupData);
3817836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&stmfGroupData;
3827836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
3837836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
3847836SJohn.Forte@Sun.COM 		switch (errno) {
3857836SJohn.Forte@Sun.COM 			case EBUSY:
3869884STim.Szeto@Sun.COM 				switch (stmfIoctl.stmf_error) {
3879884STim.Szeto@Sun.COM 					case STMF_IOCERR_TG_NEED_TG_OFFLINE:
3889884STim.Szeto@Sun.COM 						ret = STMF_ERROR_TG_ONLINE;
3899884STim.Szeto@Sun.COM 						break;
3909884STim.Szeto@Sun.COM 					default:
3919884STim.Szeto@Sun.COM 						ret = STMF_ERROR_BUSY;
3929884STim.Szeto@Sun.COM 						break;
3939884STim.Szeto@Sun.COM 				}
3947836SJohn.Forte@Sun.COM 				break;
3959585STim.Szeto@Sun.COM 			case EPERM:
3967836SJohn.Forte@Sun.COM 			case EACCES:
3977836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
3987836SJohn.Forte@Sun.COM 				break;
3997836SJohn.Forte@Sun.COM 			default:
4007836SJohn.Forte@Sun.COM 				switch (stmfIoctl.stmf_error) {
4017836SJohn.Forte@Sun.COM 					case STMF_IOCERR_TG_ENTRY_EXISTS:
4027836SJohn.Forte@Sun.COM 					case STMF_IOCERR_HG_ENTRY_EXISTS:
4037836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_EXISTS;
4047836SJohn.Forte@Sun.COM 						break;
4057836SJohn.Forte@Sun.COM 					case STMF_IOCERR_INVALID_TG_ENTRY:
4067836SJohn.Forte@Sun.COM 					case STMF_IOCERR_INVALID_HG_ENTRY:
4077836SJohn.Forte@Sun.COM 						ret =
4087836SJohn.Forte@Sun.COM 						    STMF_ERROR_MEMBER_NOT_FOUND;
4097836SJohn.Forte@Sun.COM 						break;
4107836SJohn.Forte@Sun.COM 					case STMF_IOCERR_INVALID_TG:
4117836SJohn.Forte@Sun.COM 					case STMF_IOCERR_INVALID_HG:
4127836SJohn.Forte@Sun.COM 						ret =
4137836SJohn.Forte@Sun.COM 						    STMF_ERROR_GROUP_NOT_FOUND;
4147836SJohn.Forte@Sun.COM 						break;
4157836SJohn.Forte@Sun.COM 					default:
4167836SJohn.Forte@Sun.COM 						syslog(LOG_DEBUG,
4177836SJohn.Forte@Sun.COM 						    "groupMemberIoctl:error"
4187836SJohn.Forte@Sun.COM 						    "(%d)",
4197836SJohn.Forte@Sun.COM 						    stmfIoctl.stmf_error);
4207836SJohn.Forte@Sun.COM 						ret = STMF_STATUS_ERROR;
4217836SJohn.Forte@Sun.COM 						break;
4227836SJohn.Forte@Sun.COM 				}
4237836SJohn.Forte@Sun.COM 				break;
4247836SJohn.Forte@Sun.COM 		}
4257836SJohn.Forte@Sun.COM 	}
4267836SJohn.Forte@Sun.COM done:
4277836SJohn.Forte@Sun.COM 	return (ret);
4287836SJohn.Forte@Sun.COM }
4297836SJohn.Forte@Sun.COM 
4307836SJohn.Forte@Sun.COM /*
4319585STim.Szeto@Sun.COM  * qsort function
4329585STim.Szeto@Sun.COM  * sort on veIndex
4339585STim.Szeto@Sun.COM  */
4349585STim.Szeto@Sun.COM static int
4359585STim.Szeto@Sun.COM viewEntryCompare(const void *p1, const void *p2)
4369585STim.Szeto@Sun.COM {
4379585STim.Szeto@Sun.COM 
4389585STim.Szeto@Sun.COM 	stmfViewEntry *v1 = (stmfViewEntry *)p1, *v2 = (stmfViewEntry *)p2;
4399585STim.Szeto@Sun.COM 	if (v1->veIndex > v2->veIndex)
4409585STim.Szeto@Sun.COM 		return (1);
4419585STim.Szeto@Sun.COM 	if (v1->veIndex < v2->veIndex)
4429585STim.Szeto@Sun.COM 		return (-1);
4439585STim.Szeto@Sun.COM 	return (0);
4449585STim.Szeto@Sun.COM }
4459585STim.Szeto@Sun.COM 
4469585STim.Szeto@Sun.COM /*
4477836SJohn.Forte@Sun.COM  * guidCompare
4487836SJohn.Forte@Sun.COM  *
4497836SJohn.Forte@Sun.COM  * qsort function
4507836SJohn.Forte@Sun.COM  * sort on guid
4517836SJohn.Forte@Sun.COM  */
4527836SJohn.Forte@Sun.COM static int
4537836SJohn.Forte@Sun.COM guidCompare(const void *p1, const void *p2)
4547836SJohn.Forte@Sun.COM {
4557836SJohn.Forte@Sun.COM 
4567836SJohn.Forte@Sun.COM 	stmfGuid *g1 = (stmfGuid *)p1, *g2 = (stmfGuid *)p2;
4577836SJohn.Forte@Sun.COM 	int i;
4587836SJohn.Forte@Sun.COM 
4597836SJohn.Forte@Sun.COM 	for (i = 0; i < sizeof (stmfGuid); i++) {
4607836SJohn.Forte@Sun.COM 		if (g1->guid[i] > g2->guid[i])
4617836SJohn.Forte@Sun.COM 			return (1);
4627836SJohn.Forte@Sun.COM 		if (g1->guid[i] < g2->guid[i])
4637836SJohn.Forte@Sun.COM 			return (-1);
4647836SJohn.Forte@Sun.COM 	}
4657836SJohn.Forte@Sun.COM 
4667836SJohn.Forte@Sun.COM 	return (0);
4677836SJohn.Forte@Sun.COM }
4687836SJohn.Forte@Sun.COM 
4697836SJohn.Forte@Sun.COM /*
4707836SJohn.Forte@Sun.COM  * stmfAddToHostGroup
4717836SJohn.Forte@Sun.COM  *
4727836SJohn.Forte@Sun.COM  * Purpose: Adds an initiator to an existing host group
4737836SJohn.Forte@Sun.COM  *
4747836SJohn.Forte@Sun.COM  * hostGroupName - name of an existing host group
4757836SJohn.Forte@Sun.COM  * hostName - name of initiator to add
4767836SJohn.Forte@Sun.COM  */
4777836SJohn.Forte@Sun.COM int
4787836SJohn.Forte@Sun.COM stmfAddToHostGroup(stmfGroupName *hostGroupName, stmfDevid *hostName)
4797836SJohn.Forte@Sun.COM {
4807836SJohn.Forte@Sun.COM 	int ret;
4817836SJohn.Forte@Sun.COM 	int fd;
4827836SJohn.Forte@Sun.COM 
4837836SJohn.Forte@Sun.COM 	if (hostGroupName == NULL ||
4847836SJohn.Forte@Sun.COM 	    (strnlen((char *)hostGroupName, sizeof (stmfGroupName))
4857836SJohn.Forte@Sun.COM 	    == sizeof (stmfGroupName)) || hostName == NULL) {
4867836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
4877836SJohn.Forte@Sun.COM 	}
4887836SJohn.Forte@Sun.COM 
4897836SJohn.Forte@Sun.COM 	/* call init */
4907836SJohn.Forte@Sun.COM 	ret = initializeConfig();
4917836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
4927836SJohn.Forte@Sun.COM 		return (ret);
4937836SJohn.Forte@Sun.COM 	}
4947836SJohn.Forte@Sun.COM 
4957836SJohn.Forte@Sun.COM 	/*
4967836SJohn.Forte@Sun.COM 	 * Open control node for stmf
4977836SJohn.Forte@Sun.COM 	 */
4987836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
4997836SJohn.Forte@Sun.COM 		return (ret);
5007836SJohn.Forte@Sun.COM 
5017836SJohn.Forte@Sun.COM 	if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_HG_ENTRY, hostGroupName,
5027836SJohn.Forte@Sun.COM 	    hostName)) != STMF_STATUS_SUCCESS) {
5037836SJohn.Forte@Sun.COM 		goto done;
5047836SJohn.Forte@Sun.COM 	}
5057836SJohn.Forte@Sun.COM 
5069585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
5079585STim.Szeto@Sun.COM 		goto done;
5089585STim.Szeto@Sun.COM 	}
5099585STim.Szeto@Sun.COM 
5107836SJohn.Forte@Sun.COM 	ret = psAddHostGroupMember((char *)hostGroupName,
5117836SJohn.Forte@Sun.COM 	    (char *)hostName->ident);
5127836SJohn.Forte@Sun.COM 	switch (ret) {
5137836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
5147836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
5157836SJohn.Forte@Sun.COM 			break;
5167836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_EXISTS:
5177836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_EXISTS;
5187836SJohn.Forte@Sun.COM 			break;
5197836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_GROUP_NOT_FOUND:
5207836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_GROUP_NOT_FOUND;
5217836SJohn.Forte@Sun.COM 			break;
5227836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
5237836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
5247836SJohn.Forte@Sun.COM 			break;
5257836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
5267836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
5277836SJohn.Forte@Sun.COM 			break;
5287836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
5297836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
5307836SJohn.Forte@Sun.COM 			break;
5317836SJohn.Forte@Sun.COM 		default:
5327836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
5337836SJohn.Forte@Sun.COM 			    "stmfAddToHostGroup:psAddHostGroupMember:error(%d)",
5347836SJohn.Forte@Sun.COM 			    ret);
5357836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
5367836SJohn.Forte@Sun.COM 			break;
5377836SJohn.Forte@Sun.COM 	}
5387836SJohn.Forte@Sun.COM 
5397836SJohn.Forte@Sun.COM done:
5407836SJohn.Forte@Sun.COM 	(void) close(fd);
5417836SJohn.Forte@Sun.COM 	return (ret);
5427836SJohn.Forte@Sun.COM }
5437836SJohn.Forte@Sun.COM 
5447836SJohn.Forte@Sun.COM /*
5457836SJohn.Forte@Sun.COM  * stmfAddToTargetGroup
5467836SJohn.Forte@Sun.COM  *
5477836SJohn.Forte@Sun.COM  * Purpose: Adds a local port to an existing target group
5487836SJohn.Forte@Sun.COM  *
5497836SJohn.Forte@Sun.COM  * targetGroupName - name of an existing target group
5507836SJohn.Forte@Sun.COM  * targetName - name of target to add
5517836SJohn.Forte@Sun.COM  */
5527836SJohn.Forte@Sun.COM int
5537836SJohn.Forte@Sun.COM stmfAddToTargetGroup(stmfGroupName *targetGroupName, stmfDevid *targetName)
5547836SJohn.Forte@Sun.COM {
5557836SJohn.Forte@Sun.COM 	int ret;
5567836SJohn.Forte@Sun.COM 	int fd;
5577836SJohn.Forte@Sun.COM 
5587836SJohn.Forte@Sun.COM 	if (targetGroupName == NULL ||
5597836SJohn.Forte@Sun.COM 	    (strnlen((char *)targetGroupName, sizeof (stmfGroupName))
5607836SJohn.Forte@Sun.COM 	    == sizeof (stmfGroupName)) || targetName == NULL) {
5617836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
5627836SJohn.Forte@Sun.COM 	}
5637836SJohn.Forte@Sun.COM 
5647836SJohn.Forte@Sun.COM 	/* call init */
5657836SJohn.Forte@Sun.COM 	ret = initializeConfig();
5667836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
5677836SJohn.Forte@Sun.COM 		return (ret);
5687836SJohn.Forte@Sun.COM 	}
5697836SJohn.Forte@Sun.COM 
5707836SJohn.Forte@Sun.COM 	/*
5717836SJohn.Forte@Sun.COM 	 * Open control node for stmf
5727836SJohn.Forte@Sun.COM 	 */
5737836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
5747836SJohn.Forte@Sun.COM 		return (ret);
5757836SJohn.Forte@Sun.COM 
5767836SJohn.Forte@Sun.COM 	if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_TG_ENTRY,
5777836SJohn.Forte@Sun.COM 	    targetGroupName, targetName)) != STMF_STATUS_SUCCESS) {
5787836SJohn.Forte@Sun.COM 		goto done;
5797836SJohn.Forte@Sun.COM 	}
5807836SJohn.Forte@Sun.COM 
5819585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
5829585STim.Szeto@Sun.COM 		goto done;
5839585STim.Szeto@Sun.COM 	}
5849585STim.Szeto@Sun.COM 
5857836SJohn.Forte@Sun.COM 	ret = psAddTargetGroupMember((char *)targetGroupName,
5867836SJohn.Forte@Sun.COM 	    (char *)targetName->ident);
5877836SJohn.Forte@Sun.COM 	switch (ret) {
5887836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
5897836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
5907836SJohn.Forte@Sun.COM 			break;
5917836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_EXISTS:
5927836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_EXISTS;
5937836SJohn.Forte@Sun.COM 			break;
5947836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_GROUP_NOT_FOUND:
5957836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_GROUP_NOT_FOUND;
5967836SJohn.Forte@Sun.COM 			break;
5977836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
5987836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
5997836SJohn.Forte@Sun.COM 			break;
6007836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
6017836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
6027836SJohn.Forte@Sun.COM 			break;
6037836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
6047836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
6057836SJohn.Forte@Sun.COM 			break;
6067836SJohn.Forte@Sun.COM 		default:
6077836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
6087836SJohn.Forte@Sun.COM 			    "stmfAddToTargetGroup:psAddTargetGroupMember:"
6097836SJohn.Forte@Sun.COM 			    "error(%d)", ret);
6107836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
6117836SJohn.Forte@Sun.COM 			break;
6127836SJohn.Forte@Sun.COM 	}
6137836SJohn.Forte@Sun.COM 
6147836SJohn.Forte@Sun.COM done:
6157836SJohn.Forte@Sun.COM 	(void) close(fd);
6167836SJohn.Forte@Sun.COM 	return (ret);
6177836SJohn.Forte@Sun.COM }
6187836SJohn.Forte@Sun.COM 
6197836SJohn.Forte@Sun.COM /*
6207836SJohn.Forte@Sun.COM  * addViewEntryIoctl
6217836SJohn.Forte@Sun.COM  *
6227836SJohn.Forte@Sun.COM  * Purpose: Issues ioctl to add a view entry
6237836SJohn.Forte@Sun.COM  *
6247836SJohn.Forte@Sun.COM  * lu - Logical Unit identifier to which the view entry is added
6257836SJohn.Forte@Sun.COM  * viewEntry - view entry to add
6267836SJohn.Forte@Sun.COM  * init - When set to B_TRUE, we are in the init state, i.e. don't call open
6277836SJohn.Forte@Sun.COM  */
6287836SJohn.Forte@Sun.COM static int
6297836SJohn.Forte@Sun.COM addViewEntryIoctl(int fd, stmfGuid *lu, stmfViewEntry *viewEntry)
6307836SJohn.Forte@Sun.COM {
6317836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
6327836SJohn.Forte@Sun.COM 	int ioctlRet;
6337836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
6347836SJohn.Forte@Sun.COM 	stmf_view_op_entry_t ioctlViewEntry;
6357836SJohn.Forte@Sun.COM 
6367836SJohn.Forte@Sun.COM 	bzero(&ioctlViewEntry, sizeof (ioctlViewEntry));
6377836SJohn.Forte@Sun.COM 	/*
6387836SJohn.Forte@Sun.COM 	 * don't set ve_ndx or ve_ndx_valid as ve_ndx_valid should be
6397836SJohn.Forte@Sun.COM 	 * false on input
6407836SJohn.Forte@Sun.COM 	 */
6417836SJohn.Forte@Sun.COM 	ioctlViewEntry.ve_lu_number_valid = viewEntry->luNbrValid;
6427836SJohn.Forte@Sun.COM 	ioctlViewEntry.ve_all_hosts = viewEntry->allHosts;
6437836SJohn.Forte@Sun.COM 	ioctlViewEntry.ve_all_targets = viewEntry->allTargets;
6447836SJohn.Forte@Sun.COM 
6457836SJohn.Forte@Sun.COM 	if (viewEntry->allHosts == B_FALSE) {
6467836SJohn.Forte@Sun.COM 		bcopy(viewEntry->hostGroup, &ioctlViewEntry.ve_host_group.name,
6477836SJohn.Forte@Sun.COM 		    sizeof (stmfGroupName));
6487836SJohn.Forte@Sun.COM 		ioctlViewEntry.ve_host_group.name_size =
6497836SJohn.Forte@Sun.COM 		    strlen((char *)viewEntry->hostGroup);
6507836SJohn.Forte@Sun.COM 	}
6517836SJohn.Forte@Sun.COM 	if (viewEntry->allTargets == B_FALSE) {
6527836SJohn.Forte@Sun.COM 		bcopy(viewEntry->targetGroup,
6537836SJohn.Forte@Sun.COM 		    &ioctlViewEntry.ve_target_group.name,
6547836SJohn.Forte@Sun.COM 		    sizeof (stmfGroupName));
6557836SJohn.Forte@Sun.COM 		ioctlViewEntry.ve_target_group.name_size =
6567836SJohn.Forte@Sun.COM 		    strlen((char *)viewEntry->targetGroup);
6577836SJohn.Forte@Sun.COM 	}
6587836SJohn.Forte@Sun.COM 	if (viewEntry->luNbrValid) {
6597836SJohn.Forte@Sun.COM 		bcopy(viewEntry->luNbr, &ioctlViewEntry.ve_lu_nbr,
6607836SJohn.Forte@Sun.COM 		    sizeof (ioctlViewEntry.ve_lu_nbr));
6617836SJohn.Forte@Sun.COM 	}
6627836SJohn.Forte@Sun.COM 	bcopy(lu, &ioctlViewEntry.ve_guid, sizeof (stmfGuid));
6637836SJohn.Forte@Sun.COM 
6647836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
6657836SJohn.Forte@Sun.COM 	/*
6667836SJohn.Forte@Sun.COM 	 * Issue ioctl to add to the view entry
6677836SJohn.Forte@Sun.COM 	 */
6687836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
6697836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry);
6707836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry;
6717836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = sizeof (ioctlViewEntry);
6727836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&ioctlViewEntry;
6737836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_ADD_VIEW_ENTRY, &stmfIoctl);
6747836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
6757836SJohn.Forte@Sun.COM 		switch (errno) {
6767836SJohn.Forte@Sun.COM 			case EBUSY:
6777836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
6787836SJohn.Forte@Sun.COM 				break;
6799585STim.Szeto@Sun.COM 			case EPERM:
6809585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
6819585STim.Szeto@Sun.COM 				break;
6827836SJohn.Forte@Sun.COM 			case EACCES:
6837836SJohn.Forte@Sun.COM 				switch (stmfIoctl.stmf_error) {
6847836SJohn.Forte@Sun.COM 					case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
6857836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_CONFIG_NONE;
6867836SJohn.Forte@Sun.COM 						break;
6877836SJohn.Forte@Sun.COM 					default:
6887836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_PERM;
6897836SJohn.Forte@Sun.COM 						break;
6907836SJohn.Forte@Sun.COM 				}
6917836SJohn.Forte@Sun.COM 				break;
6927836SJohn.Forte@Sun.COM 			default:
6937836SJohn.Forte@Sun.COM 				switch (stmfIoctl.stmf_error) {
6947836SJohn.Forte@Sun.COM 					case STMF_IOCERR_LU_NUMBER_IN_USE:
6957836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_LUN_IN_USE;
6967836SJohn.Forte@Sun.COM 						break;
6977836SJohn.Forte@Sun.COM 					case STMF_IOCERR_VIEW_ENTRY_CONFLICT:
6987836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_VE_CONFLICT;
6997836SJohn.Forte@Sun.COM 						break;
7007836SJohn.Forte@Sun.COM 					case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
7017836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_CONFIG_NONE;
7027836SJohn.Forte@Sun.COM 						break;
7037836SJohn.Forte@Sun.COM 					case STMF_IOCERR_INVALID_HG:
7047836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_INVALID_HG;
7057836SJohn.Forte@Sun.COM 						break;
7067836SJohn.Forte@Sun.COM 					case STMF_IOCERR_INVALID_TG:
7077836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_INVALID_TG;
7087836SJohn.Forte@Sun.COM 						break;
7097836SJohn.Forte@Sun.COM 					default:
7107836SJohn.Forte@Sun.COM 						syslog(LOG_DEBUG,
7117836SJohn.Forte@Sun.COM 						    "addViewEntryIoctl"
7127836SJohn.Forte@Sun.COM 						    ":error(%d)",
7137836SJohn.Forte@Sun.COM 						    stmfIoctl.stmf_error);
7147836SJohn.Forte@Sun.COM 						ret = STMF_STATUS_ERROR;
7157836SJohn.Forte@Sun.COM 						break;
7167836SJohn.Forte@Sun.COM 				}
7177836SJohn.Forte@Sun.COM 				break;
7187836SJohn.Forte@Sun.COM 		}
7197836SJohn.Forte@Sun.COM 		goto done;
7207836SJohn.Forte@Sun.COM 	}
7217836SJohn.Forte@Sun.COM 
7227836SJohn.Forte@Sun.COM 	/* copy lu nbr back to caller's view entry on success */
7237836SJohn.Forte@Sun.COM 	viewEntry->veIndex = ioctlViewEntry.ve_ndx;
7247836SJohn.Forte@Sun.COM 	if (ioctlViewEntry.ve_lu_number_valid) {
7257836SJohn.Forte@Sun.COM 		bcopy(&ioctlViewEntry.ve_lu_nbr, viewEntry->luNbr,
7267836SJohn.Forte@Sun.COM 		    sizeof (ioctlViewEntry.ve_lu_nbr));
7277836SJohn.Forte@Sun.COM 	}
7287836SJohn.Forte@Sun.COM 	viewEntry->luNbrValid = B_TRUE;
7297836SJohn.Forte@Sun.COM 
7307836SJohn.Forte@Sun.COM done:
7317836SJohn.Forte@Sun.COM 	return (ret);
7327836SJohn.Forte@Sun.COM }
7337836SJohn.Forte@Sun.COM 
7347836SJohn.Forte@Sun.COM /*
7357836SJohn.Forte@Sun.COM  * stmfAddViewEntry
7367836SJohn.Forte@Sun.COM  *
7377836SJohn.Forte@Sun.COM  * Purpose: Adds a view entry to a logical unit
7387836SJohn.Forte@Sun.COM  *
7397836SJohn.Forte@Sun.COM  * lu - guid of the logical unit to which the view entry is added
7407836SJohn.Forte@Sun.COM  * viewEntry - view entry structure to add
7417836SJohn.Forte@Sun.COM  */
7427836SJohn.Forte@Sun.COM int
7437836SJohn.Forte@Sun.COM stmfAddViewEntry(stmfGuid *lu, stmfViewEntry *viewEntry)
7447836SJohn.Forte@Sun.COM {
7457836SJohn.Forte@Sun.COM 	int ret;
7467836SJohn.Forte@Sun.COM 	int fd;
7477836SJohn.Forte@Sun.COM 	stmfViewEntry iViewEntry;
7487836SJohn.Forte@Sun.COM 
7497836SJohn.Forte@Sun.COM 	if (lu == NULL || viewEntry == NULL) {
7507836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
7517836SJohn.Forte@Sun.COM 	}
7527836SJohn.Forte@Sun.COM 
7537836SJohn.Forte@Sun.COM 	/* initialize and set internal view entry */
7547836SJohn.Forte@Sun.COM 	bzero(&iViewEntry, sizeof (iViewEntry));
7557836SJohn.Forte@Sun.COM 
7567836SJohn.Forte@Sun.COM 	if (!viewEntry->allHosts) {
7577836SJohn.Forte@Sun.COM 		bcopy(viewEntry->hostGroup, iViewEntry.hostGroup,
7587836SJohn.Forte@Sun.COM 		    sizeof (iViewEntry.hostGroup));
7597836SJohn.Forte@Sun.COM 	} else {
7607836SJohn.Forte@Sun.COM 		iViewEntry.allHosts = B_TRUE;
7617836SJohn.Forte@Sun.COM 	}
7627836SJohn.Forte@Sun.COM 
7637836SJohn.Forte@Sun.COM 	if (!viewEntry->allTargets) {
7647836SJohn.Forte@Sun.COM 		bcopy(viewEntry->targetGroup, iViewEntry.targetGroup,
7657836SJohn.Forte@Sun.COM 		    sizeof (iViewEntry.targetGroup));
7667836SJohn.Forte@Sun.COM 	} else {
7677836SJohn.Forte@Sun.COM 		iViewEntry.allTargets = B_TRUE;
7687836SJohn.Forte@Sun.COM 	}
7697836SJohn.Forte@Sun.COM 
7707836SJohn.Forte@Sun.COM 	if (viewEntry->luNbrValid) {
7717836SJohn.Forte@Sun.COM 		iViewEntry.luNbrValid = B_TRUE;
7727836SJohn.Forte@Sun.COM 		bcopy(viewEntry->luNbr, iViewEntry.luNbr,
7737836SJohn.Forte@Sun.COM 		    sizeof (iViewEntry.luNbr));
7747836SJohn.Forte@Sun.COM 	}
7757836SJohn.Forte@Sun.COM 
7767836SJohn.Forte@Sun.COM 	/*
7777836SJohn.Forte@Sun.COM 	 * set users return view entry index valid flag to false
7787836SJohn.Forte@Sun.COM 	 * in case of failure
7797836SJohn.Forte@Sun.COM 	 */
7807836SJohn.Forte@Sun.COM 	viewEntry->veIndexValid = B_FALSE;
7817836SJohn.Forte@Sun.COM 
7827836SJohn.Forte@Sun.COM 	/* Check to ensure service exists */
7837836SJohn.Forte@Sun.COM 	if (psCheckService() != STMF_STATUS_SUCCESS) {
7847836SJohn.Forte@Sun.COM 		return (STMF_ERROR_SERVICE_NOT_FOUND);
7857836SJohn.Forte@Sun.COM 	}
7867836SJohn.Forte@Sun.COM 
7877836SJohn.Forte@Sun.COM 	/* call init */
7887836SJohn.Forte@Sun.COM 	ret = initializeConfig();
7897836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
7907836SJohn.Forte@Sun.COM 		return (ret);
7917836SJohn.Forte@Sun.COM 	}
7927836SJohn.Forte@Sun.COM 
7937836SJohn.Forte@Sun.COM 	/*
7947836SJohn.Forte@Sun.COM 	 * Open control node for stmf
7957836SJohn.Forte@Sun.COM 	 */
7967836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
7977836SJohn.Forte@Sun.COM 		return (ret);
7987836SJohn.Forte@Sun.COM 
7997836SJohn.Forte@Sun.COM 	/*
8007836SJohn.Forte@Sun.COM 	 * First add the view entry to the driver
8017836SJohn.Forte@Sun.COM 	 */
8027836SJohn.Forte@Sun.COM 	ret = addViewEntryIoctl(fd, lu, &iViewEntry);
8037836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
8047836SJohn.Forte@Sun.COM 		goto done;
8057836SJohn.Forte@Sun.COM 	}
8067836SJohn.Forte@Sun.COM 
8079585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
8089585STim.Szeto@Sun.COM 		goto done;
8099585STim.Szeto@Sun.COM 	}
8109585STim.Szeto@Sun.COM 
8117836SJohn.Forte@Sun.COM 	/*
8127836SJohn.Forte@Sun.COM 	 * If the add to driver was successful, add it to the persistent
8137836SJohn.Forte@Sun.COM 	 * store.
8147836SJohn.Forte@Sun.COM 	 */
8157836SJohn.Forte@Sun.COM 	ret = psAddViewEntry(lu, &iViewEntry);
8167836SJohn.Forte@Sun.COM 	switch (ret) {
8177836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
8187836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
8197836SJohn.Forte@Sun.COM 			break;
8207836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
8217836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
8227836SJohn.Forte@Sun.COM 			break;
8237836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
8247836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
8257836SJohn.Forte@Sun.COM 			break;
8267836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
8277836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
8287836SJohn.Forte@Sun.COM 			break;
8297836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
8307836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
8317836SJohn.Forte@Sun.COM 			break;
8327836SJohn.Forte@Sun.COM 		default:
8337836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
8347836SJohn.Forte@Sun.COM 			    "stmfAddViewEntry:psAddViewEntry:error(%d)", ret);
8357836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
8367836SJohn.Forte@Sun.COM 			break;
8377836SJohn.Forte@Sun.COM 	}
8387836SJohn.Forte@Sun.COM 
8397836SJohn.Forte@Sun.COM done:
8407836SJohn.Forte@Sun.COM 	(void) close(fd);
8417836SJohn.Forte@Sun.COM 
8427836SJohn.Forte@Sun.COM 	if (ret == STMF_STATUS_SUCCESS) {
8437836SJohn.Forte@Sun.COM 		/* set caller's view entry on success */
8447836SJohn.Forte@Sun.COM 		viewEntry->veIndexValid = iViewEntry.veIndexValid;
8457836SJohn.Forte@Sun.COM 		viewEntry->veIndex = iViewEntry.veIndex;
8467836SJohn.Forte@Sun.COM 		viewEntry->luNbrValid = B_TRUE;
8477836SJohn.Forte@Sun.COM 		bcopy(iViewEntry.luNbr, viewEntry->luNbr,
8487836SJohn.Forte@Sun.COM 		    sizeof (iViewEntry.luNbr));
8497836SJohn.Forte@Sun.COM 	}
8507836SJohn.Forte@Sun.COM 	return (ret);
8517836SJohn.Forte@Sun.COM }
8527836SJohn.Forte@Sun.COM 
8537836SJohn.Forte@Sun.COM /*
8547836SJohn.Forte@Sun.COM  * stmfClearProviderData
8557836SJohn.Forte@Sun.COM  *
8567836SJohn.Forte@Sun.COM  * Purpose: delete all provider data for specified provider
8577836SJohn.Forte@Sun.COM  *
8587836SJohn.Forte@Sun.COM  * providerName - name of provider for which data should be deleted
8597836SJohn.Forte@Sun.COM  */
8607836SJohn.Forte@Sun.COM int
8617836SJohn.Forte@Sun.COM stmfClearProviderData(char *providerName, int providerType)
8627836SJohn.Forte@Sun.COM {
8637836SJohn.Forte@Sun.COM 	int ret;
8647836SJohn.Forte@Sun.COM 	int fd;
8657836SJohn.Forte@Sun.COM 	int ioctlRet;
8667836SJohn.Forte@Sun.COM 	int savedErrno;
8677836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
8687836SJohn.Forte@Sun.COM 	stmf_ppioctl_data_t ppi;
8697836SJohn.Forte@Sun.COM 
8707836SJohn.Forte@Sun.COM 	/* call init */
8717836SJohn.Forte@Sun.COM 	ret = initializeConfig();
8727836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
8737836SJohn.Forte@Sun.COM 		return (ret);
8747836SJohn.Forte@Sun.COM 	}
8757836SJohn.Forte@Sun.COM 
8767836SJohn.Forte@Sun.COM 	if (providerName == NULL) {
8777836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
8787836SJohn.Forte@Sun.COM 	}
8797836SJohn.Forte@Sun.COM 
8807836SJohn.Forte@Sun.COM 	if (providerType != STMF_LU_PROVIDER_TYPE &&
8817836SJohn.Forte@Sun.COM 	    providerType != STMF_PORT_PROVIDER_TYPE) {
8827836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
8837836SJohn.Forte@Sun.COM 	}
8847836SJohn.Forte@Sun.COM 
8857836SJohn.Forte@Sun.COM 	/*
8867836SJohn.Forte@Sun.COM 	 * Open control node for stmf
8877836SJohn.Forte@Sun.COM 	 */
8887836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
8897836SJohn.Forte@Sun.COM 		return (ret);
8907836SJohn.Forte@Sun.COM 
8917836SJohn.Forte@Sun.COM 	bzero(&ppi, sizeof (ppi));
8927836SJohn.Forte@Sun.COM 
8937836SJohn.Forte@Sun.COM 	(void) strncpy(ppi.ppi_name, providerName, sizeof (ppi.ppi_name));
8947836SJohn.Forte@Sun.COM 
8957836SJohn.Forte@Sun.COM 	switch (providerType) {
8967836SJohn.Forte@Sun.COM 		case STMF_LU_PROVIDER_TYPE:
8977836SJohn.Forte@Sun.COM 			ppi.ppi_lu_provider = 1;
8987836SJohn.Forte@Sun.COM 			break;
8997836SJohn.Forte@Sun.COM 		case STMF_PORT_PROVIDER_TYPE:
9007836SJohn.Forte@Sun.COM 			ppi.ppi_port_provider = 1;
9017836SJohn.Forte@Sun.COM 			break;
9027836SJohn.Forte@Sun.COM 		default:
9037836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_INVALID_ARG;
9047836SJohn.Forte@Sun.COM 			goto done;
9057836SJohn.Forte@Sun.COM 	}
9067836SJohn.Forte@Sun.COM 
9077836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
9087836SJohn.Forte@Sun.COM 
9097836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
9107836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (stmf_ppioctl_data_t);
9117836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ppi;
9127836SJohn.Forte@Sun.COM 
9137836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_CLEAR_PP_DATA, &stmfIoctl);
9147836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
9157836SJohn.Forte@Sun.COM 		savedErrno = errno;
9167836SJohn.Forte@Sun.COM 		switch (savedErrno) {
9177836SJohn.Forte@Sun.COM 			case EBUSY:
9187836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
9197836SJohn.Forte@Sun.COM 				break;
9209585STim.Szeto@Sun.COM 			case EPERM:
9217836SJohn.Forte@Sun.COM 			case EACCES:
9227836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
9237836SJohn.Forte@Sun.COM 				break;
9247836SJohn.Forte@Sun.COM 			default:
9257836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
9267836SJohn.Forte@Sun.COM 				    "stmfClearProviderData:ioctl error(%d)",
9277836SJohn.Forte@Sun.COM 				    ioctlRet);
9287836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
9297836SJohn.Forte@Sun.COM 				break;
9307836SJohn.Forte@Sun.COM 		}
9317836SJohn.Forte@Sun.COM 		if (savedErrno != ENOENT) {
9327836SJohn.Forte@Sun.COM 			goto done;
9337836SJohn.Forte@Sun.COM 		}
9347836SJohn.Forte@Sun.COM 	}
9357836SJohn.Forte@Sun.COM 
9369585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
9379585STim.Szeto@Sun.COM 		goto done;
9389585STim.Szeto@Sun.COM 	}
9399585STim.Szeto@Sun.COM 
9407836SJohn.Forte@Sun.COM 	ret = psClearProviderData(providerName, providerType);
9417836SJohn.Forte@Sun.COM 	switch (ret) {
9427836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
9437836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
9447836SJohn.Forte@Sun.COM 			break;
9457836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
9467836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
9477836SJohn.Forte@Sun.COM 			break;
9487836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
9497836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
9507836SJohn.Forte@Sun.COM 			break;
9517836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
9527836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
9537836SJohn.Forte@Sun.COM 			break;
9547836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
9557836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
9567836SJohn.Forte@Sun.COM 			break;
9577836SJohn.Forte@Sun.COM 		default:
9587836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
9597836SJohn.Forte@Sun.COM 			    "stmfClearProviderData:psClearProviderData"
9607836SJohn.Forte@Sun.COM 			    ":error(%d)", ret);
9617836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
9627836SJohn.Forte@Sun.COM 			break;
9637836SJohn.Forte@Sun.COM 	}
9647836SJohn.Forte@Sun.COM 
9657836SJohn.Forte@Sun.COM done:
9667836SJohn.Forte@Sun.COM 	(void) close(fd);
9677836SJohn.Forte@Sun.COM 	return (ret);
9687836SJohn.Forte@Sun.COM }
9697836SJohn.Forte@Sun.COM 
9707836SJohn.Forte@Sun.COM /*
9717836SJohn.Forte@Sun.COM  * stmfCreateHostGroup
9727836SJohn.Forte@Sun.COM  *
9737836SJohn.Forte@Sun.COM  * Purpose: Create a new initiator group
9747836SJohn.Forte@Sun.COM  *
9757836SJohn.Forte@Sun.COM  * hostGroupName - name of host group to create
9767836SJohn.Forte@Sun.COM  */
9777836SJohn.Forte@Sun.COM int
9787836SJohn.Forte@Sun.COM stmfCreateHostGroup(stmfGroupName *hostGroupName)
9797836SJohn.Forte@Sun.COM {
9807836SJohn.Forte@Sun.COM 	int ret;
9817836SJohn.Forte@Sun.COM 	int fd;
9827836SJohn.Forte@Sun.COM 
9837836SJohn.Forte@Sun.COM 	if (hostGroupName == NULL ||
9847836SJohn.Forte@Sun.COM 	    (strnlen((char *)hostGroupName, sizeof (stmfGroupName))
9857836SJohn.Forte@Sun.COM 	    == sizeof (stmfGroupName))) {
9867836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
9877836SJohn.Forte@Sun.COM 	}
9887836SJohn.Forte@Sun.COM 
9897836SJohn.Forte@Sun.COM 	/* Check to ensure service exists */
9907836SJohn.Forte@Sun.COM 	if (psCheckService() != STMF_STATUS_SUCCESS) {
9917836SJohn.Forte@Sun.COM 		return (STMF_ERROR_SERVICE_NOT_FOUND);
9927836SJohn.Forte@Sun.COM 	}
9937836SJohn.Forte@Sun.COM 
9947836SJohn.Forte@Sun.COM 	/* call init */
9957836SJohn.Forte@Sun.COM 	ret = initializeConfig();
9967836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
9977836SJohn.Forte@Sun.COM 		return (ret);
9987836SJohn.Forte@Sun.COM 	}
9997836SJohn.Forte@Sun.COM 
10007836SJohn.Forte@Sun.COM 	/*
10017836SJohn.Forte@Sun.COM 	 * Open control node for stmf
10027836SJohn.Forte@Sun.COM 	 */
10037836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
10047836SJohn.Forte@Sun.COM 		return (ret);
10057836SJohn.Forte@Sun.COM 
10067836SJohn.Forte@Sun.COM 	if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_HOST_GROUP,
10077836SJohn.Forte@Sun.COM 	    hostGroupName)) != STMF_STATUS_SUCCESS) {
10087836SJohn.Forte@Sun.COM 		goto done;
10097836SJohn.Forte@Sun.COM 	}
10107836SJohn.Forte@Sun.COM 
10119585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
10129585STim.Szeto@Sun.COM 		goto done;
10139585STim.Szeto@Sun.COM 	}
10149585STim.Szeto@Sun.COM 
10157836SJohn.Forte@Sun.COM 	ret = psCreateHostGroup((char *)hostGroupName);
10167836SJohn.Forte@Sun.COM 	switch (ret) {
10177836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
10187836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
10197836SJohn.Forte@Sun.COM 			break;
10207836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_EXISTS:
10217836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_EXISTS;
10227836SJohn.Forte@Sun.COM 			break;
10237836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
10247836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
10257836SJohn.Forte@Sun.COM 			break;
10267836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
10277836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
10287836SJohn.Forte@Sun.COM 			break;
10297836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
10307836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
10317836SJohn.Forte@Sun.COM 			break;
10327836SJohn.Forte@Sun.COM 		default:
10337836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
10347836SJohn.Forte@Sun.COM 			    "stmfCreateHostGroup:psCreateHostGroup:error(%d)",
10357836SJohn.Forte@Sun.COM 			    ret);
10367836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
10377836SJohn.Forte@Sun.COM 			break;
10387836SJohn.Forte@Sun.COM 	}
10397836SJohn.Forte@Sun.COM 
10407836SJohn.Forte@Sun.COM done:
10417836SJohn.Forte@Sun.COM 	(void) close(fd);
10427836SJohn.Forte@Sun.COM 	return (ret);
10437836SJohn.Forte@Sun.COM }
10447836SJohn.Forte@Sun.COM 
10457836SJohn.Forte@Sun.COM /*
10469585STim.Szeto@Sun.COM  * stmfCreateLu
10479585STim.Szeto@Sun.COM  *
10489585STim.Szeto@Sun.COM  * Purpose: Create a logical unit
10499585STim.Szeto@Sun.COM  *
10509585STim.Szeto@Sun.COM  * hdl - handle to logical unit resource created via stmfCreateLuResource
10519585STim.Szeto@Sun.COM  *
10529585STim.Szeto@Sun.COM  * luGuid - If non-NULL, on success, contains the guid of the created logical
10539585STim.Szeto@Sun.COM  *	    unit
10549585STim.Szeto@Sun.COM  */
10559585STim.Szeto@Sun.COM int
10569585STim.Szeto@Sun.COM stmfCreateLu(luResource hdl, stmfGuid *luGuid)
10579585STim.Szeto@Sun.COM {
10589585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
10599585STim.Szeto@Sun.COM 	luResourceImpl *luPropsHdl = hdl;
10609585STim.Szeto@Sun.COM 
10619585STim.Szeto@Sun.COM 	if (hdl == NULL) {
10629585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
10639585STim.Szeto@Sun.COM 	}
10649585STim.Szeto@Sun.COM 
10659585STim.Szeto@Sun.COM 	if (luPropsHdl->type == STMF_DISK) {
10669585STim.Szeto@Sun.COM 		ret = createDiskLu((diskResource *)luPropsHdl->resource,
10679585STim.Szeto@Sun.COM 		    luGuid);
10689585STim.Szeto@Sun.COM 	} else {
10699585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
10709585STim.Szeto@Sun.COM 	}
10719585STim.Szeto@Sun.COM 
10729585STim.Szeto@Sun.COM 	return (ret);
10739585STim.Szeto@Sun.COM }
10749585STim.Szeto@Sun.COM 
10759585STim.Szeto@Sun.COM /*
10769585STim.Szeto@Sun.COM  * stmfCreateLuResource
10779585STim.Szeto@Sun.COM  *
10789585STim.Szeto@Sun.COM  * Purpose: Create resource handle for a logical unit
10799585STim.Szeto@Sun.COM  *
10809585STim.Szeto@Sun.COM  * dType - Type of logical unit resource to create
10819585STim.Szeto@Sun.COM  *	   Can be: STMF_DISK
10829585STim.Szeto@Sun.COM  *
10839585STim.Szeto@Sun.COM  * hdl - pointer to luResource
10849585STim.Szeto@Sun.COM  */
10859585STim.Szeto@Sun.COM int
10869585STim.Szeto@Sun.COM stmfCreateLuResource(uint16_t dType, luResource *hdl)
10879585STim.Szeto@Sun.COM {
10889585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
10899585STim.Szeto@Sun.COM 
10909585STim.Szeto@Sun.COM 	if (dType != STMF_DISK || hdl == NULL) {
10919585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
10929585STim.Szeto@Sun.COM 	}
10939585STim.Szeto@Sun.COM 
10949585STim.Szeto@Sun.COM 	*hdl = calloc(1, sizeof (luResourceImpl));
10959585STim.Szeto@Sun.COM 	if (*hdl == NULL) {
10969585STim.Szeto@Sun.COM 		return (STMF_ERROR_NOMEM);
10979585STim.Szeto@Sun.COM 	}
10989585STim.Szeto@Sun.COM 
10999585STim.Szeto@Sun.COM 	ret = createDiskResource((luResourceImpl *)*hdl);
11009585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
11019585STim.Szeto@Sun.COM 		free(*hdl);
11029585STim.Szeto@Sun.COM 		return (ret);
11039585STim.Szeto@Sun.COM 	}
11049585STim.Szeto@Sun.COM 
11059585STim.Szeto@Sun.COM 	return (STMF_STATUS_SUCCESS);
11069585STim.Szeto@Sun.COM }
11079585STim.Szeto@Sun.COM 
11089585STim.Szeto@Sun.COM /*
11099585STim.Szeto@Sun.COM  * Creates a disk logical unit
11109585STim.Szeto@Sun.COM  *
11119585STim.Szeto@Sun.COM  * disk - pointer to diskResource structure that represents the properties
11129585STim.Szeto@Sun.COM  *        for the disk logical unit to be created.
11139585STim.Szeto@Sun.COM  */
11149585STim.Szeto@Sun.COM static int
11159585STim.Szeto@Sun.COM createDiskLu(diskResource *disk, stmfGuid *createdGuid)
11169585STim.Szeto@Sun.COM {
11179585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
11189585STim.Szeto@Sun.COM 	int dataFileNameLen = 0;
11199585STim.Szeto@Sun.COM 	int metaFileNameLen = 0;
11209585STim.Szeto@Sun.COM 	int serialNumLen = 0;
11219585STim.Szeto@Sun.COM 	int luAliasLen = 0;
112210113SNattuvetty.Bhavyan@Sun.COM 	int luMgmtUrlLen = 0;
11239585STim.Szeto@Sun.COM 	int sluBufSize = 0;
11249585STim.Szeto@Sun.COM 	int bufOffset = 0;
11259585STim.Szeto@Sun.COM 	int fd = 0;
11269585STim.Szeto@Sun.COM 	int ioctlRet;
11279585STim.Szeto@Sun.COM 	int savedErrno;
11289585STim.Szeto@Sun.COM 	stmfGuid guid;
11299585STim.Szeto@Sun.COM 	stmf_iocdata_t sbdIoctl = {0};
11309585STim.Szeto@Sun.COM 
11319585STim.Szeto@Sun.COM 	sbd_create_and_reg_lu_t *sbdLu = NULL;
11329585STim.Szeto@Sun.COM 
11339585STim.Szeto@Sun.COM 	/*
11349585STim.Szeto@Sun.COM 	 * Open control node for sbd
11359585STim.Szeto@Sun.COM 	 */
11369585STim.Szeto@Sun.COM 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
11379585STim.Szeto@Sun.COM 		return (ret);
11389585STim.Szeto@Sun.COM 
11399585STim.Szeto@Sun.COM 	/* data file name must be specified */
11409585STim.Szeto@Sun.COM 	if (disk->luDataFileNameValid) {
11419585STim.Szeto@Sun.COM 		dataFileNameLen = strlen(disk->luDataFileName);
11429585STim.Szeto@Sun.COM 	} else {
11439585STim.Szeto@Sun.COM 		(void) close(fd);
11449585STim.Szeto@Sun.COM 		return (STMF_ERROR_MISSING_PROP_VAL);
11459585STim.Szeto@Sun.COM 	}
11469585STim.Szeto@Sun.COM 
11479585STim.Szeto@Sun.COM 	sluBufSize += dataFileNameLen + 1;
11489585STim.Szeto@Sun.COM 
11499585STim.Szeto@Sun.COM 	if (disk->luMetaFileNameValid) {
11509585STim.Szeto@Sun.COM 		metaFileNameLen = strlen(disk->luMetaFileName);
11519585STim.Szeto@Sun.COM 		sluBufSize += metaFileNameLen + 1;
11529585STim.Szeto@Sun.COM 	}
11539585STim.Szeto@Sun.COM 
11549585STim.Szeto@Sun.COM 	serialNumLen = strlen(disk->serialNum);
11559585STim.Szeto@Sun.COM 	sluBufSize += serialNumLen;
11569585STim.Szeto@Sun.COM 
11579585STim.Szeto@Sun.COM 	if (disk->luAliasValid) {
11589585STim.Szeto@Sun.COM 		luAliasLen = strlen(disk->luAlias);
11599585STim.Szeto@Sun.COM 		sluBufSize += luAliasLen + 1;
11609585STim.Szeto@Sun.COM 	}
11619585STim.Szeto@Sun.COM 
116210113SNattuvetty.Bhavyan@Sun.COM 	if (disk->luMgmtUrlValid) {
116310113SNattuvetty.Bhavyan@Sun.COM 		luMgmtUrlLen = strlen(disk->luMgmtUrl);
116410113SNattuvetty.Bhavyan@Sun.COM 		sluBufSize += luMgmtUrlLen + 1;
116510113SNattuvetty.Bhavyan@Sun.COM 	}
116610113SNattuvetty.Bhavyan@Sun.COM 
11679585STim.Szeto@Sun.COM 	/*
11689585STim.Szeto@Sun.COM 	 * 8 is the size of the buffer set aside for
11699585STim.Szeto@Sun.COM 	 * concatenation of variable length fields
11709585STim.Szeto@Sun.COM 	 */
11719585STim.Szeto@Sun.COM 	sbdLu = (sbd_create_and_reg_lu_t *)calloc(1,
11729585STim.Szeto@Sun.COM 	    sizeof (sbd_create_and_reg_lu_t) + sluBufSize - 8);
11739585STim.Szeto@Sun.COM 	if (sbdLu == NULL) {
11749585STim.Szeto@Sun.COM 		return (STMF_ERROR_NOMEM);
11759585STim.Szeto@Sun.COM 	}
11769585STim.Szeto@Sun.COM 
11779585STim.Szeto@Sun.COM 	sbdLu->slu_struct_size = sizeof (sbd_create_and_reg_lu_t) +
11789585STim.Szeto@Sun.COM 	    sluBufSize - 8;
11799585STim.Szeto@Sun.COM 
11809585STim.Szeto@Sun.COM 	if (metaFileNameLen) {
11819585STim.Szeto@Sun.COM 		sbdLu->slu_meta_fname_valid = 1;
11829585STim.Szeto@Sun.COM 		sbdLu->slu_meta_fname_off = bufOffset;
11839585STim.Szeto@Sun.COM 		bcopy(disk->luMetaFileName, &(sbdLu->slu_buf[bufOffset]),
11849585STim.Szeto@Sun.COM 		    metaFileNameLen + 1);
11859585STim.Szeto@Sun.COM 		bufOffset += metaFileNameLen + 1;
11869585STim.Szeto@Sun.COM 	}
11879585STim.Szeto@Sun.COM 
11889585STim.Szeto@Sun.COM 	bcopy(disk->luDataFileName, &(sbdLu->slu_buf[bufOffset]),
11899585STim.Szeto@Sun.COM 	    dataFileNameLen + 1);
11909585STim.Szeto@Sun.COM 	sbdLu->slu_data_fname_off = bufOffset;
11919585STim.Szeto@Sun.COM 	bufOffset += dataFileNameLen + 1;
11929585STim.Szeto@Sun.COM 
11939585STim.Szeto@Sun.COM 	/* currently, serial # is not passed null terminated to the driver */
11949585STim.Szeto@Sun.COM 	if (disk->serialNumValid) {
11959585STim.Szeto@Sun.COM 		sbdLu->slu_serial_valid = 1;
11969585STim.Szeto@Sun.COM 		sbdLu->slu_serial_off = bufOffset;
11979585STim.Szeto@Sun.COM 		sbdLu->slu_serial_size = serialNumLen;
11989585STim.Szeto@Sun.COM 		bcopy(disk->serialNum, &(sbdLu->slu_buf[bufOffset]),
11999585STim.Szeto@Sun.COM 		    serialNumLen);
12009585STim.Szeto@Sun.COM 		bufOffset += serialNumLen;
12019585STim.Szeto@Sun.COM 	}
12029585STim.Szeto@Sun.COM 
12039585STim.Szeto@Sun.COM 	if (disk->luAliasValid) {
12049585STim.Szeto@Sun.COM 		sbdLu->slu_alias_valid = 1;
12059585STim.Szeto@Sun.COM 		sbdLu->slu_alias_off = bufOffset;
12069585STim.Szeto@Sun.COM 		bcopy(disk->luAlias, &(sbdLu->slu_buf[bufOffset]),
12079585STim.Szeto@Sun.COM 		    luAliasLen + 1);
12089585STim.Szeto@Sun.COM 		bufOffset += luAliasLen + 1;
12099585STim.Szeto@Sun.COM 	}
12109585STim.Szeto@Sun.COM 
121110113SNattuvetty.Bhavyan@Sun.COM 	if (disk->luMgmtUrlValid) {
121210113SNattuvetty.Bhavyan@Sun.COM 		sbdLu->slu_mgmt_url_valid = 1;
121310113SNattuvetty.Bhavyan@Sun.COM 		sbdLu->slu_mgmt_url_off = bufOffset;
121410113SNattuvetty.Bhavyan@Sun.COM 		bcopy(disk->luMgmtUrl, &(sbdLu->slu_buf[bufOffset]),
121510113SNattuvetty.Bhavyan@Sun.COM 		    luMgmtUrlLen + 1);
121610113SNattuvetty.Bhavyan@Sun.COM 		bufOffset += luMgmtUrlLen + 1;
121710113SNattuvetty.Bhavyan@Sun.COM 	}
121810113SNattuvetty.Bhavyan@Sun.COM 
12199585STim.Szeto@Sun.COM 	if (disk->luSizeValid) {
12209585STim.Szeto@Sun.COM 		sbdLu->slu_lu_size_valid = 1;
12219585STim.Szeto@Sun.COM 		sbdLu->slu_lu_size = disk->luSize;
12229585STim.Szeto@Sun.COM 	}
12239585STim.Szeto@Sun.COM 
12249585STim.Szeto@Sun.COM 	if (disk->luGuidValid) {
12259585STim.Szeto@Sun.COM 		sbdLu->slu_guid_valid = 1;
12269585STim.Szeto@Sun.COM 		bcopy(disk->luGuid, sbdLu->slu_guid, sizeof (disk->luGuid));
12279585STim.Szeto@Sun.COM 	}
12289585STim.Szeto@Sun.COM 
12299585STim.Szeto@Sun.COM 	if (disk->vidValid) {
12309585STim.Szeto@Sun.COM 		sbdLu->slu_vid_valid = 1;
12319585STim.Szeto@Sun.COM 		bcopy(disk->vid, sbdLu->slu_vid, sizeof (disk->vid));
12329585STim.Szeto@Sun.COM 	}
12339585STim.Szeto@Sun.COM 
12349585STim.Szeto@Sun.COM 	if (disk->pidValid) {
12359585STim.Szeto@Sun.COM 		sbdLu->slu_pid_valid = 1;
12369585STim.Szeto@Sun.COM 		bcopy(disk->pid, sbdLu->slu_pid, sizeof (disk->pid));
12379585STim.Szeto@Sun.COM 	}
12389585STim.Szeto@Sun.COM 
12399585STim.Szeto@Sun.COM 	if (disk->revValid) {
12409585STim.Szeto@Sun.COM 		sbdLu->slu_rev_valid = 1;
12419585STim.Szeto@Sun.COM 		bcopy(disk->rev, sbdLu->slu_rev, sizeof (disk->rev));
12429585STim.Szeto@Sun.COM 	}
12439585STim.Szeto@Sun.COM 
12449585STim.Szeto@Sun.COM 	if (disk->companyIdValid) {
12459585STim.Szeto@Sun.COM 		sbdLu->slu_company_id_valid = 1;
12469585STim.Szeto@Sun.COM 		sbdLu->slu_company_id = disk->companyId;
12479585STim.Szeto@Sun.COM 	}
12489585STim.Szeto@Sun.COM 
124910765SJohn.Forte@Sun.COM 	if (disk->hostIdValid) {
125010765SJohn.Forte@Sun.COM 		sbdLu->slu_host_id_valid = 1;
125110765SJohn.Forte@Sun.COM 		sbdLu->slu_host_id = disk->hostId;
125210765SJohn.Forte@Sun.COM 	}
125310765SJohn.Forte@Sun.COM 
12549585STim.Szeto@Sun.COM 	if (disk->blkSizeValid) {
12559585STim.Szeto@Sun.COM 		sbdLu->slu_blksize_valid = 1;
12569585STim.Szeto@Sun.COM 		sbdLu->slu_blksize = disk->blkSize;
12579585STim.Szeto@Sun.COM 	}
12589585STim.Szeto@Sun.COM 
12599585STim.Szeto@Sun.COM 	if (disk->writeProtectEnableValid) {
12609585STim.Szeto@Sun.COM 		if (disk->writeProtectEnable) {
12619585STim.Szeto@Sun.COM 			sbdLu->slu_write_protected = 1;
12629585STim.Szeto@Sun.COM 		}
12639585STim.Szeto@Sun.COM 	}
12649585STim.Szeto@Sun.COM 
12659585STim.Szeto@Sun.COM 	if (disk->writebackCacheDisableValid) {
12669585STim.Szeto@Sun.COM 		sbdLu->slu_writeback_cache_disable_valid = 1;
12679585STim.Szeto@Sun.COM 		if (disk->writebackCacheDisable) {
12689585STim.Szeto@Sun.COM 			sbdLu->slu_writeback_cache_disable = 1;
12699585STim.Szeto@Sun.COM 		}
12709585STim.Szeto@Sun.COM 	}
12719585STim.Szeto@Sun.COM 
12729585STim.Szeto@Sun.COM 	sbdIoctl.stmf_version = STMF_VERSION_1;
12739585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf_size = sbdLu->slu_struct_size;
12749585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdLu;
12759585STim.Szeto@Sun.COM 	sbdIoctl.stmf_obuf_size = sbdLu->slu_struct_size;
12769585STim.Szeto@Sun.COM 	sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdLu;
12779585STim.Szeto@Sun.COM 
12789585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, SBD_IOCTL_CREATE_AND_REGISTER_LU, &sbdIoctl);
12799585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
12809585STim.Szeto@Sun.COM 		savedErrno = errno;
12819585STim.Szeto@Sun.COM 		switch (savedErrno) {
12829585STim.Szeto@Sun.COM 			case EBUSY:
12839585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
12849585STim.Szeto@Sun.COM 				break;
12859585STim.Szeto@Sun.COM 			case EPERM:
12869585STim.Szeto@Sun.COM 			case EACCES:
12879585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
12889585STim.Szeto@Sun.COM 				break;
12899585STim.Szeto@Sun.COM 			default:
12909585STim.Szeto@Sun.COM 				diskError(sbdIoctl.stmf_error, &ret);
12919585STim.Szeto@Sun.COM 				if (ret == STMF_STATUS_ERROR) {
12929585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
12939585STim.Szeto@Sun.COM 					"createDiskLu:ioctl "
12949585STim.Szeto@Sun.COM 					"error(%d) (%d) (%d)", ioctlRet,
12959585STim.Szeto@Sun.COM 					    sbdIoctl.stmf_error, savedErrno);
12969585STim.Szeto@Sun.COM 				}
12979585STim.Szeto@Sun.COM 				break;
12989585STim.Szeto@Sun.COM 		}
12999585STim.Szeto@Sun.COM 	}
13009585STim.Szeto@Sun.COM 
13019585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
13029585STim.Szeto@Sun.COM 		goto done;
13039585STim.Szeto@Sun.COM 	}
13049585STim.Szeto@Sun.COM 
13059585STim.Szeto@Sun.COM 	/*
13069585STim.Szeto@Sun.COM 	 * on success, copy the resulting guid into the caller's guid if not
13079585STim.Szeto@Sun.COM 	 * NULL
13089585STim.Szeto@Sun.COM 	 */
13099585STim.Szeto@Sun.COM 	if (createdGuid) {
13109585STim.Szeto@Sun.COM 		bcopy(sbdLu->slu_guid, createdGuid->guid,
13119585STim.Szeto@Sun.COM 		    sizeof (sbdLu->slu_guid));
13129585STim.Szeto@Sun.COM 	}
13139585STim.Szeto@Sun.COM 
13149585STim.Szeto@Sun.COM 	bcopy(sbdLu->slu_guid, guid.guid, sizeof (sbdLu->slu_guid));
13159585STim.Szeto@Sun.COM 	if (disk->luMetaFileNameValid) {
13169585STim.Szeto@Sun.COM 		ret = addGuidToDiskStore(&guid, disk->luMetaFileName);
13179585STim.Szeto@Sun.COM 	} else {
13189585STim.Szeto@Sun.COM 		ret = addGuidToDiskStore(&guid, disk->luDataFileName);
13199585STim.Szeto@Sun.COM 	}
13209585STim.Szeto@Sun.COM done:
13219585STim.Szeto@Sun.COM 	free(sbdLu);
13229585STim.Szeto@Sun.COM 	(void) close(fd);
13239585STim.Szeto@Sun.COM 	return (ret);
13249585STim.Szeto@Sun.COM }
13259585STim.Szeto@Sun.COM 
13269585STim.Szeto@Sun.COM 
13279585STim.Szeto@Sun.COM /*
13289585STim.Szeto@Sun.COM  * stmfImportLu
13299585STim.Szeto@Sun.COM  *
13309585STim.Szeto@Sun.COM  * Purpose: Import a previously created logical unit
13319585STim.Szeto@Sun.COM  *
13329585STim.Szeto@Sun.COM  * dType - Type of logical unit
13339585STim.Szeto@Sun.COM  *         Can be: STMF_DISK
13349585STim.Szeto@Sun.COM  *
13359585STim.Szeto@Sun.COM  * luGuid - If non-NULL, on success, contains the guid of the imported logical
13369585STim.Szeto@Sun.COM  *	    unit
13379585STim.Szeto@Sun.COM  *
13389585STim.Szeto@Sun.COM  * fname - A file name where the metadata resides
13399585STim.Szeto@Sun.COM  *
13409585STim.Szeto@Sun.COM  */
13419585STim.Szeto@Sun.COM int
13429585STim.Szeto@Sun.COM stmfImportLu(uint16_t dType, char *fname, stmfGuid *luGuid)
13439585STim.Szeto@Sun.COM {
13449585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
13459585STim.Szeto@Sun.COM 
13469585STim.Szeto@Sun.COM 	if (dType == STMF_DISK) {
13479585STim.Szeto@Sun.COM 		ret = importDiskLu(fname, luGuid);
13489585STim.Szeto@Sun.COM 	} else {
13499585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
13509585STim.Szeto@Sun.COM 	}
13519585STim.Szeto@Sun.COM 
13529585STim.Szeto@Sun.COM 	return (ret);
13539585STim.Szeto@Sun.COM }
13549585STim.Szeto@Sun.COM 
13559585STim.Szeto@Sun.COM /*
13569585STim.Szeto@Sun.COM  * importDiskLu
13579585STim.Szeto@Sun.COM  *
13589585STim.Szeto@Sun.COM  * filename - filename to import
13599585STim.Szeto@Sun.COM  * createdGuid - if not NULL, on success contains the imported guid
13609585STim.Szeto@Sun.COM  *
13619585STim.Szeto@Sun.COM  */
13629585STim.Szeto@Sun.COM static int
13639585STim.Szeto@Sun.COM importDiskLu(char *fname, stmfGuid *createdGuid)
13649585STim.Szeto@Sun.COM {
13659585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
13669585STim.Szeto@Sun.COM 	int fd = 0;
13679585STim.Szeto@Sun.COM 	int ioctlRet;
13689585STim.Szeto@Sun.COM 	int savedErrno;
13699585STim.Szeto@Sun.COM 	int metaFileNameLen;
13709585STim.Szeto@Sun.COM 	stmfGuid iGuid;
13719585STim.Szeto@Sun.COM 	int iluBufSize = 0;
13729585STim.Szeto@Sun.COM 	sbd_import_lu_t *sbdLu = NULL;
13739585STim.Szeto@Sun.COM 	stmf_iocdata_t sbdIoctl = {0};
13749585STim.Szeto@Sun.COM 
13759585STim.Szeto@Sun.COM 	if (fname == NULL) {
13769585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
13779585STim.Szeto@Sun.COM 	}
13789585STim.Szeto@Sun.COM 
13799585STim.Szeto@Sun.COM 	/*
13809585STim.Szeto@Sun.COM 	 * Open control node for sbd
13819585STim.Szeto@Sun.COM 	 */
13829585STim.Szeto@Sun.COM 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
13839585STim.Szeto@Sun.COM 		return (ret);
13849585STim.Szeto@Sun.COM 
13859585STim.Szeto@Sun.COM 	metaFileNameLen = strlen(fname);
13869585STim.Szeto@Sun.COM 	iluBufSize += metaFileNameLen + 1;
13879585STim.Szeto@Sun.COM 
13889585STim.Szeto@Sun.COM 	/*
13899585STim.Szeto@Sun.COM 	 * 8 is the size of the buffer set aside for
13909585STim.Szeto@Sun.COM 	 * concatenation of variable length fields
13919585STim.Szeto@Sun.COM 	 */
13929585STim.Szeto@Sun.COM 	sbdLu = (sbd_import_lu_t *)calloc(1,
13939585STim.Szeto@Sun.COM 	    sizeof (sbd_import_lu_t) + iluBufSize - 8);
13949585STim.Szeto@Sun.COM 	if (sbdLu == NULL) {
13959585STim.Szeto@Sun.COM 		(void) close(fd);
13969585STim.Szeto@Sun.COM 		return (STMF_ERROR_NOMEM);
13979585STim.Szeto@Sun.COM 	}
13989585STim.Szeto@Sun.COM 
13999585STim.Szeto@Sun.COM 	/*
14009585STim.Szeto@Sun.COM 	 * Accept either a data file or meta data file.
14019585STim.Szeto@Sun.COM 	 * sbd will do the right thing here either way.
14029585STim.Szeto@Sun.COM 	 * i.e. if it's a data file, it assumes that the
14039585STim.Szeto@Sun.COM 	 * meta data is shared with the data.
14049585STim.Szeto@Sun.COM 	 */
14059585STim.Szeto@Sun.COM 	(void) strncpy(sbdLu->ilu_meta_fname, fname, metaFileNameLen);
14069585STim.Szeto@Sun.COM 
14079585STim.Szeto@Sun.COM 	sbdLu->ilu_struct_size = sizeof (sbd_import_lu_t) + iluBufSize - 8;
14089585STim.Szeto@Sun.COM 
14099585STim.Szeto@Sun.COM 	sbdIoctl.stmf_version = STMF_VERSION_1;
14109585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf_size = sbdLu->ilu_struct_size;
14119585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdLu;
14129585STim.Szeto@Sun.COM 	sbdIoctl.stmf_obuf_size = sbdLu->ilu_struct_size;
14139585STim.Szeto@Sun.COM 	sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdLu;
14149585STim.Szeto@Sun.COM 
14159585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, SBD_IOCTL_IMPORT_LU, &sbdIoctl);
14169585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
14179585STim.Szeto@Sun.COM 		savedErrno = errno;
14189585STim.Szeto@Sun.COM 		switch (savedErrno) {
14199585STim.Szeto@Sun.COM 			case EBUSY:
14209585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
14219585STim.Szeto@Sun.COM 				break;
14229585STim.Szeto@Sun.COM 			case EPERM:
14239585STim.Szeto@Sun.COM 			case EACCES:
14249585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
14259585STim.Szeto@Sun.COM 				break;
14269585STim.Szeto@Sun.COM 			default:
14279585STim.Szeto@Sun.COM 				diskError(sbdIoctl.stmf_error, &ret);
14289585STim.Szeto@Sun.COM 				if (ret == STMF_STATUS_ERROR) {
14299585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
14309585STim.Szeto@Sun.COM 					"importDiskLu:ioctl "
14319585STim.Szeto@Sun.COM 					"error(%d) (%d) (%d)", ioctlRet,
14329585STim.Szeto@Sun.COM 					    sbdIoctl.stmf_error, savedErrno);
14339585STim.Szeto@Sun.COM 				}
14349585STim.Szeto@Sun.COM 				break;
14359585STim.Szeto@Sun.COM 		}
14369585STim.Szeto@Sun.COM 	}
14379585STim.Szeto@Sun.COM 
14389585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
14399585STim.Szeto@Sun.COM 		goto done;
14409585STim.Szeto@Sun.COM 	}
14419585STim.Szeto@Sun.COM 
14429585STim.Szeto@Sun.COM 	/*
14439585STim.Szeto@Sun.COM 	 * on success, copy the resulting guid into the caller's guid if not
14449585STim.Szeto@Sun.COM 	 * NULL and add it to the persistent store for sbd
14459585STim.Szeto@Sun.COM 	 */
14469585STim.Szeto@Sun.COM 	if (createdGuid) {
14479585STim.Szeto@Sun.COM 		bcopy(sbdLu->ilu_ret_guid, createdGuid->guid,
14489585STim.Szeto@Sun.COM 		    sizeof (sbdLu->ilu_ret_guid));
14499585STim.Szeto@Sun.COM 		ret = addGuidToDiskStore(createdGuid, fname);
14509585STim.Szeto@Sun.COM 	} else {
14519585STim.Szeto@Sun.COM 		bcopy(sbdLu->ilu_ret_guid, iGuid.guid,
14529585STim.Szeto@Sun.COM 		    sizeof (sbdLu->ilu_ret_guid));
14539585STim.Szeto@Sun.COM 		ret = addGuidToDiskStore(&iGuid, fname);
14549585STim.Szeto@Sun.COM 	}
14559585STim.Szeto@Sun.COM done:
14569585STim.Szeto@Sun.COM 	free(sbdLu);
14579585STim.Szeto@Sun.COM 	(void) close(fd);
14589585STim.Szeto@Sun.COM 	return (ret);
14599585STim.Szeto@Sun.COM }
14609585STim.Szeto@Sun.COM 
14619585STim.Szeto@Sun.COM /*
14629585STim.Szeto@Sun.COM  * diskError
14639585STim.Szeto@Sun.COM  *
14649585STim.Szeto@Sun.COM  * Purpose: Translate sbd driver error
14659585STim.Szeto@Sun.COM  */
14669585STim.Szeto@Sun.COM static void
14679585STim.Szeto@Sun.COM diskError(uint32_t stmfError, int *ret)
14689585STim.Szeto@Sun.COM {
14699585STim.Szeto@Sun.COM 	switch (stmfError) {
14709585STim.Szeto@Sun.COM 		case SBD_RET_META_CREATION_FAILED:
14719585STim.Szeto@Sun.COM 		case SBD_RET_ZFS_META_CREATE_FAILED:
14729585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_META_CREATION;
14739585STim.Szeto@Sun.COM 			break;
14749585STim.Szeto@Sun.COM 		case SBD_RET_INVALID_BLKSIZE:
14759585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_INVALID_BLKSIZE;
14769585STim.Szeto@Sun.COM 			break;
14779585STim.Szeto@Sun.COM 		case SBD_RET_FILE_ALREADY_REGISTERED:
14789585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_FILE_IN_USE;
14799585STim.Szeto@Sun.COM 			break;
14809585STim.Szeto@Sun.COM 		case SBD_RET_GUID_ALREADY_REGISTERED:
14819585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_GUID_IN_USE;
14829585STim.Szeto@Sun.COM 			break;
14839585STim.Szeto@Sun.COM 		case SBD_RET_META_PATH_NOT_ABSOLUTE:
14849585STim.Szeto@Sun.COM 		case SBD_RET_META_FILE_LOOKUP_FAILED:
14859585STim.Szeto@Sun.COM 		case SBD_RET_META_FILE_OPEN_FAILED:
14869585STim.Szeto@Sun.COM 		case SBD_RET_META_FILE_GETATTR_FAILED:
14879585STim.Szeto@Sun.COM 		case SBD_RET_NO_META:
14889585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_META_FILE_NAME;
14899585STim.Szeto@Sun.COM 			break;
14909585STim.Szeto@Sun.COM 		case SBD_RET_DATA_PATH_NOT_ABSOLUTE:
14919585STim.Szeto@Sun.COM 		case SBD_RET_DATA_FILE_LOOKUP_FAILED:
14929585STim.Szeto@Sun.COM 		case SBD_RET_DATA_FILE_OPEN_FAILED:
14939585STim.Szeto@Sun.COM 		case SBD_RET_DATA_FILE_GETATTR_FAILED:
14949585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_DATA_FILE_NAME;
14959585STim.Szeto@Sun.COM 			break;
14969585STim.Szeto@Sun.COM 		case SBD_RET_FILE_SIZE_ERROR:
14979585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_FILE_SIZE_INVALID;
14989585STim.Szeto@Sun.COM 			break;
14999585STim.Szeto@Sun.COM 		case SBD_RET_SIZE_OUT_OF_RANGE:
15009585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_SIZE_OUT_OF_RANGE;
15019585STim.Szeto@Sun.COM 			break;
15029585STim.Szeto@Sun.COM 		case SBD_RET_LU_BUSY:
15039585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_LU_BUSY;
15049585STim.Szeto@Sun.COM 			break;
15059585STim.Szeto@Sun.COM 		case SBD_RET_WRITE_CACHE_SET_FAILED:
15069585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_WRITE_CACHE_SET;
15079585STim.Szeto@Sun.COM 			break;
150810725SJohn.Forte@Sun.COM 		case SBD_RET_ACCESS_STATE_FAILED:
150910725SJohn.Forte@Sun.COM 			*ret = STMF_ERROR_ACCESS_STATE_SET;
151010725SJohn.Forte@Sun.COM 			break;
15119585STim.Szeto@Sun.COM 		default:
15129585STim.Szeto@Sun.COM 			*ret = STMF_STATUS_ERROR;
15139585STim.Szeto@Sun.COM 			break;
15149585STim.Szeto@Sun.COM 	}
15159585STim.Szeto@Sun.COM }
15169585STim.Szeto@Sun.COM 
15179585STim.Szeto@Sun.COM /*
15189585STim.Szeto@Sun.COM  * Creates a logical unit resource of type STMF_DISK.
15199585STim.Szeto@Sun.COM  *
15209585STim.Szeto@Sun.COM  * No defaults should be set here as all defaults are derived from the
15219585STim.Szeto@Sun.COM  * driver's default settings.
15229585STim.Szeto@Sun.COM  */
15239585STim.Szeto@Sun.COM static int
15249585STim.Szeto@Sun.COM createDiskResource(luResourceImpl *hdl)
15259585STim.Szeto@Sun.COM {
15269585STim.Szeto@Sun.COM 	hdl->type = STMF_DISK;
15279585STim.Szeto@Sun.COM 
15289585STim.Szeto@Sun.COM 	hdl->resource = calloc(1, sizeof (diskResource));
15299585STim.Szeto@Sun.COM 	if (hdl->resource == NULL) {
15309585STim.Szeto@Sun.COM 		return (STMF_ERROR_NOMEM);
15319585STim.Szeto@Sun.COM 	}
15329585STim.Szeto@Sun.COM 
15339585STim.Szeto@Sun.COM 	return (STMF_STATUS_SUCCESS);
15349585STim.Szeto@Sun.COM }
15359585STim.Szeto@Sun.COM 
15369585STim.Szeto@Sun.COM /*
15379585STim.Szeto@Sun.COM  * stmfDeleteLu
15389585STim.Szeto@Sun.COM  *
15399585STim.Szeto@Sun.COM  * Purpose: Delete a logical unit
15409585STim.Szeto@Sun.COM  *
15419585STim.Szeto@Sun.COM  * hdl - handle to logical unit resource created via stmfCreateLuResource
15429585STim.Szeto@Sun.COM  *
15439585STim.Szeto@Sun.COM  * luGuid - If non-NULL, on success, contains the guid of the created logical
15449585STim.Szeto@Sun.COM  *	    unit
15459585STim.Szeto@Sun.COM  */
15469585STim.Szeto@Sun.COM int
15479585STim.Szeto@Sun.COM stmfDeleteLu(stmfGuid *luGuid)
15489585STim.Szeto@Sun.COM {
15499585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
15509585STim.Szeto@Sun.COM 	stmfLogicalUnitProperties luProps;
15519585STim.Szeto@Sun.COM 
15529585STim.Szeto@Sun.COM 	if (luGuid == NULL) {
15539585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
15549585STim.Szeto@Sun.COM 	}
15559585STim.Szeto@Sun.COM 
15569585STim.Szeto@Sun.COM 	/* Check logical unit provider name to call correct dtype function */
15579585STim.Szeto@Sun.COM 	if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps))
15589585STim.Szeto@Sun.COM 	    != STMF_STATUS_SUCCESS) {
15599585STim.Szeto@Sun.COM 		return (ret);
15609585STim.Szeto@Sun.COM 	} else {
15619585STim.Szeto@Sun.COM 		if (strcmp(luProps.providerName, "sbd") == 0) {
15629585STim.Szeto@Sun.COM 			ret = deleteDiskLu(luGuid);
15639585STim.Szeto@Sun.COM 		} else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) {
15649585STim.Szeto@Sun.COM 			return (STMF_ERROR_NOT_FOUND);
15659585STim.Szeto@Sun.COM 		} else {
15669585STim.Szeto@Sun.COM 			return (STMF_ERROR_INVALID_ARG);
15679585STim.Szeto@Sun.COM 		}
15689585STim.Szeto@Sun.COM 	}
15699585STim.Szeto@Sun.COM 
15709585STim.Szeto@Sun.COM 	return (ret);
15719585STim.Szeto@Sun.COM }
15729585STim.Szeto@Sun.COM 
15739585STim.Szeto@Sun.COM static int
15749585STim.Szeto@Sun.COM deleteDiskLu(stmfGuid *luGuid)
15759585STim.Szeto@Sun.COM {
15769585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
15779585STim.Szeto@Sun.COM 	int fd;
15789585STim.Szeto@Sun.COM 	int savedErrno;
15799585STim.Szeto@Sun.COM 	int ioctlRet;
15809585STim.Szeto@Sun.COM 	sbd_delete_lu_t deleteLu = {0};
15819585STim.Szeto@Sun.COM 
15829585STim.Szeto@Sun.COM 	stmf_iocdata_t sbdIoctl = {0};
15839585STim.Szeto@Sun.COM 
15849585STim.Szeto@Sun.COM 	/*
15859585STim.Szeto@Sun.COM 	 * Open control node for sbd
15869585STim.Szeto@Sun.COM 	 */
15879585STim.Szeto@Sun.COM 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
15889585STim.Szeto@Sun.COM 		return (ret);
15899585STim.Szeto@Sun.COM 
15909585STim.Szeto@Sun.COM 	ret = removeGuidFromDiskStore(luGuid);
15919585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
15929585STim.Szeto@Sun.COM 		goto done;
15939585STim.Szeto@Sun.COM 	}
15949585STim.Szeto@Sun.COM 
15959585STim.Szeto@Sun.COM 	bcopy(luGuid, deleteLu.dlu_guid, sizeof (deleteLu.dlu_guid));
15969585STim.Szeto@Sun.COM 	deleteLu.dlu_by_guid = 1;
15979585STim.Szeto@Sun.COM 
15989585STim.Szeto@Sun.COM 	sbdIoctl.stmf_version = STMF_VERSION_1;
15999585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf_size = sizeof (deleteLu);
16009585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)&deleteLu;
16019585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, SBD_IOCTL_DELETE_LU, &sbdIoctl);
16029585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
16039585STim.Szeto@Sun.COM 		savedErrno = errno;
16049585STim.Szeto@Sun.COM 		switch (savedErrno) {
16059585STim.Szeto@Sun.COM 			case EBUSY:
16069585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
16079585STim.Szeto@Sun.COM 				break;
16089585STim.Szeto@Sun.COM 			case EPERM:
16099585STim.Szeto@Sun.COM 			case EACCES:
16109585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
16119585STim.Szeto@Sun.COM 				break;
16129585STim.Szeto@Sun.COM 			case ENOENT:
16139585STim.Szeto@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
16149585STim.Szeto@Sun.COM 				break;
16159585STim.Szeto@Sun.COM 			default:
16169585STim.Szeto@Sun.COM 				syslog(LOG_DEBUG,
16179585STim.Szeto@Sun.COM 				    "deleteDiskLu:ioctl error(%d) (%d) (%d)",
16189585STim.Szeto@Sun.COM 				    ioctlRet, sbdIoctl.stmf_error, savedErrno);
16199585STim.Szeto@Sun.COM 				ret = STMF_STATUS_ERROR;
16209585STim.Szeto@Sun.COM 				break;
16219585STim.Szeto@Sun.COM 		}
16229585STim.Szeto@Sun.COM 	}
16239585STim.Szeto@Sun.COM 
16249585STim.Szeto@Sun.COM done:
16259585STim.Szeto@Sun.COM 	(void) close(fd);
16269585STim.Szeto@Sun.COM 	return (ret);
16279585STim.Szeto@Sun.COM }
16289585STim.Szeto@Sun.COM 
16299585STim.Szeto@Sun.COM /*
163010725SJohn.Forte@Sun.COM  * stmfLuStandby
163110725SJohn.Forte@Sun.COM  *
163210725SJohn.Forte@Sun.COM  * Purpose: Sets access state to standby
163310725SJohn.Forte@Sun.COM  *
163410725SJohn.Forte@Sun.COM  * luGuid - guid of registered logical unit
163510725SJohn.Forte@Sun.COM  *
163610725SJohn.Forte@Sun.COM  */
163710725SJohn.Forte@Sun.COM int
163810725SJohn.Forte@Sun.COM stmfLuStandby(stmfGuid *luGuid)
163910725SJohn.Forte@Sun.COM {
164010725SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
164110725SJohn.Forte@Sun.COM 	stmfLogicalUnitProperties luProps;
164210725SJohn.Forte@Sun.COM 
164310725SJohn.Forte@Sun.COM 	if (luGuid == NULL) {
164410725SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
164510725SJohn.Forte@Sun.COM 	}
164610725SJohn.Forte@Sun.COM 
164710725SJohn.Forte@Sun.COM 	/* Check logical unit provider name to call correct dtype function */
164810725SJohn.Forte@Sun.COM 	if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps))
164910725SJohn.Forte@Sun.COM 	    != STMF_STATUS_SUCCESS) {
165010725SJohn.Forte@Sun.COM 		return (ret);
165110725SJohn.Forte@Sun.COM 	} else {
165210725SJohn.Forte@Sun.COM 		if (strcmp(luProps.providerName, "sbd") == 0) {
165310725SJohn.Forte@Sun.COM 			ret = setDiskStandby(luGuid);
165410725SJohn.Forte@Sun.COM 		} else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) {
165510725SJohn.Forte@Sun.COM 			return (STMF_ERROR_NOT_FOUND);
165610725SJohn.Forte@Sun.COM 		} else {
165710725SJohn.Forte@Sun.COM 			return (STMF_ERROR_INVALID_ARG);
165810725SJohn.Forte@Sun.COM 		}
165910725SJohn.Forte@Sun.COM 	}
166010725SJohn.Forte@Sun.COM 
166110725SJohn.Forte@Sun.COM 	return (ret);
166210725SJohn.Forte@Sun.COM }
166310725SJohn.Forte@Sun.COM 
166410725SJohn.Forte@Sun.COM static int
166510725SJohn.Forte@Sun.COM setDiskStandby(stmfGuid *luGuid)
166610725SJohn.Forte@Sun.COM {
166710725SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
166810725SJohn.Forte@Sun.COM 	stmf_iocdata_t sbdIoctl = {0};
166910725SJohn.Forte@Sun.COM 	sbd_set_lu_standby_t sbdLu = {0};
167010725SJohn.Forte@Sun.COM 	int ioctlRet;
167110725SJohn.Forte@Sun.COM 	int savedErrno;
167210725SJohn.Forte@Sun.COM 	int fd = 0;
167310725SJohn.Forte@Sun.COM 
167410725SJohn.Forte@Sun.COM 	/*
167510725SJohn.Forte@Sun.COM 	 * Open control node for sbd
167610725SJohn.Forte@Sun.COM 	 */
167710725SJohn.Forte@Sun.COM 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
167810725SJohn.Forte@Sun.COM 		return (ret);
167910725SJohn.Forte@Sun.COM 
168010725SJohn.Forte@Sun.COM 	bcopy(luGuid, &sbdLu.stlu_guid, sizeof (stmfGuid));
168110725SJohn.Forte@Sun.COM 
168210725SJohn.Forte@Sun.COM 	sbdIoctl.stmf_version = STMF_VERSION_1;
168310725SJohn.Forte@Sun.COM 	sbdIoctl.stmf_ibuf_size = sizeof (sbd_set_lu_standby_t);
168410725SJohn.Forte@Sun.COM 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)&sbdLu;
168510725SJohn.Forte@Sun.COM 
168610725SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, SBD_IOCTL_SET_LU_STANDBY, &sbdIoctl);
168710725SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
168810725SJohn.Forte@Sun.COM 		savedErrno = errno;
168910725SJohn.Forte@Sun.COM 		switch (savedErrno) {
169010725SJohn.Forte@Sun.COM 			case EBUSY:
169110725SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
169210725SJohn.Forte@Sun.COM 				break;
169310725SJohn.Forte@Sun.COM 			case EPERM:
169410725SJohn.Forte@Sun.COM 			case EACCES:
169510725SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
169610725SJohn.Forte@Sun.COM 				break;
169710725SJohn.Forte@Sun.COM 			default:
169810725SJohn.Forte@Sun.COM 				diskError(sbdIoctl.stmf_error, &ret);
169910725SJohn.Forte@Sun.COM 				if (ret == STMF_STATUS_ERROR) {
170010725SJohn.Forte@Sun.COM 					syslog(LOG_DEBUG,
170110725SJohn.Forte@Sun.COM 					"setDiskStandby:ioctl "
170210725SJohn.Forte@Sun.COM 					"error(%d) (%d) (%d)", ioctlRet,
170310725SJohn.Forte@Sun.COM 					    sbdIoctl.stmf_error, savedErrno);
170410725SJohn.Forte@Sun.COM 				}
170510725SJohn.Forte@Sun.COM 				break;
170610725SJohn.Forte@Sun.COM 		}
170710725SJohn.Forte@Sun.COM 	}
170810725SJohn.Forte@Sun.COM 	return (ret);
170910725SJohn.Forte@Sun.COM }
171010725SJohn.Forte@Sun.COM 
171110725SJohn.Forte@Sun.COM /*
17129585STim.Szeto@Sun.COM  * stmfModifyLu
17139585STim.Szeto@Sun.COM  *
17149585STim.Szeto@Sun.COM  * Purpose: Modify properties of a logical unit
17159585STim.Szeto@Sun.COM  *
17169585STim.Szeto@Sun.COM  * luGuid - guid of registered logical unit
17179585STim.Szeto@Sun.COM  * prop - property to modify
17189585STim.Szeto@Sun.COM  * propVal - property value to set
17199585STim.Szeto@Sun.COM  *
17209585STim.Szeto@Sun.COM  */
17219585STim.Szeto@Sun.COM int
17229585STim.Szeto@Sun.COM stmfModifyLu(stmfGuid *luGuid, uint32_t prop, const char *propVal)
17239585STim.Szeto@Sun.COM {
17249585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
17259585STim.Szeto@Sun.COM 	stmfLogicalUnitProperties luProps;
17269585STim.Szeto@Sun.COM 
17279585STim.Szeto@Sun.COM 	if (luGuid == NULL) {
17289585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
17299585STim.Szeto@Sun.COM 	}
17309585STim.Szeto@Sun.COM 
17319585STim.Szeto@Sun.COM 	/* Check logical unit provider name to call correct dtype function */
17329585STim.Szeto@Sun.COM 	if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps))
17339585STim.Szeto@Sun.COM 	    != STMF_STATUS_SUCCESS) {
17349585STim.Szeto@Sun.COM 		return (ret);
17359585STim.Szeto@Sun.COM 	} else {
17369585STim.Szeto@Sun.COM 		if (strcmp(luProps.providerName, "sbd") == 0) {
17379585STim.Szeto@Sun.COM 			ret = modifyDiskLuProp(luGuid, NULL, prop, propVal);
17389585STim.Szeto@Sun.COM 		} else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) {
17399585STim.Szeto@Sun.COM 			return (STMF_ERROR_NOT_FOUND);
17409585STim.Szeto@Sun.COM 		} else {
17419585STim.Szeto@Sun.COM 			return (STMF_ERROR_INVALID_ARG);
17429585STim.Szeto@Sun.COM 		}
17439585STim.Szeto@Sun.COM 	}
17449585STim.Szeto@Sun.COM 
17459585STim.Szeto@Sun.COM 	return (ret);
17469585STim.Szeto@Sun.COM }
17479585STim.Szeto@Sun.COM 
17489585STim.Szeto@Sun.COM /*
17499585STim.Szeto@Sun.COM  * stmfModifyLuByFname
17509585STim.Szeto@Sun.COM  *
17519585STim.Szeto@Sun.COM  * Purpose: Modify a device by filename. Device does not need to be registered.
17529585STim.Szeto@Sun.COM  *
17539585STim.Szeto@Sun.COM  * dType - type of device to modify
17549585STim.Szeto@Sun.COM  *         STMF_DISK
17559585STim.Szeto@Sun.COM  *
17569585STim.Szeto@Sun.COM  * fname - filename or meta filename
17579585STim.Szeto@Sun.COM  * prop - valid property identifier
17589585STim.Szeto@Sun.COM  * propVal - property value
17599585STim.Szeto@Sun.COM  *
17609585STim.Szeto@Sun.COM  */
17619585STim.Szeto@Sun.COM int
17629585STim.Szeto@Sun.COM stmfModifyLuByFname(uint16_t dType, const char *fname, uint32_t prop,
17639585STim.Szeto@Sun.COM     const char *propVal)
17649585STim.Szeto@Sun.COM {
17659585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
17669585STim.Szeto@Sun.COM 	if (fname == NULL) {
17679585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
17689585STim.Szeto@Sun.COM 	}
17699585STim.Szeto@Sun.COM 
17709585STim.Szeto@Sun.COM 	if (dType == STMF_DISK) {
17719585STim.Szeto@Sun.COM 		ret = modifyDiskLuProp(NULL, fname, prop, propVal);
17729585STim.Szeto@Sun.COM 	} else {
17739585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
17749585STim.Szeto@Sun.COM 	}
17759585STim.Szeto@Sun.COM 
17769585STim.Szeto@Sun.COM 	return (ret);
17779585STim.Szeto@Sun.COM }
17789585STim.Szeto@Sun.COM 
17799585STim.Szeto@Sun.COM static int
17809585STim.Szeto@Sun.COM modifyDiskLuProp(stmfGuid *luGuid, const char *fname, uint32_t prop,
17819585STim.Szeto@Sun.COM     const char *propVal)
17829585STim.Szeto@Sun.COM {
17839585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
17849585STim.Szeto@Sun.COM 	luResource hdl = NULL;
17859585STim.Szeto@Sun.COM 	luResourceImpl *luPropsHdl;
17869585STim.Szeto@Sun.COM 
17879585STim.Szeto@Sun.COM 	ret = stmfCreateLuResource(STMF_DISK, &hdl);
17889585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
17899585STim.Szeto@Sun.COM 		return (ret);
17909585STim.Szeto@Sun.COM 	}
17919585STim.Szeto@Sun.COM 	ret = validateModifyDiskProp(prop);
17929585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
17939585STim.Szeto@Sun.COM 		(void) stmfFreeLuResource(hdl);
17949585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_PROP);
17959585STim.Szeto@Sun.COM 	}
17969585STim.Szeto@Sun.COM 	ret = stmfSetLuProp(hdl, prop, propVal);
17979585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
17989585STim.Szeto@Sun.COM 		(void) stmfFreeLuResource(hdl);
17999585STim.Szeto@Sun.COM 		return (ret);
18009585STim.Szeto@Sun.COM 	}
18019585STim.Szeto@Sun.COM 	luPropsHdl = hdl;
18029585STim.Szeto@Sun.COM 	ret = modifyDiskLu((diskResource *)luPropsHdl->resource, luGuid, fname);
18039585STim.Szeto@Sun.COM 	(void) stmfFreeLuResource(hdl);
18049585STim.Szeto@Sun.COM 	return (ret);
18059585STim.Szeto@Sun.COM }
18069585STim.Szeto@Sun.COM 
18079585STim.Szeto@Sun.COM static int
18089585STim.Szeto@Sun.COM validateModifyDiskProp(uint32_t prop)
18099585STim.Szeto@Sun.COM {
18109585STim.Szeto@Sun.COM 	switch (prop) {
18119585STim.Szeto@Sun.COM 		case STMF_LU_PROP_ALIAS:
18129585STim.Szeto@Sun.COM 		case STMF_LU_PROP_SIZE:
181310113SNattuvetty.Bhavyan@Sun.COM 		case STMF_LU_PROP_MGMT_URL:
18149585STim.Szeto@Sun.COM 		case STMF_LU_PROP_WRITE_PROTECT:
18159585STim.Szeto@Sun.COM 		case STMF_LU_PROP_WRITE_CACHE_DISABLE:
18169585STim.Szeto@Sun.COM 			return (STMF_STATUS_SUCCESS);
18179585STim.Szeto@Sun.COM 			break;
18189585STim.Szeto@Sun.COM 		default:
18199585STim.Szeto@Sun.COM 			return (STMF_STATUS_ERROR);
18209585STim.Szeto@Sun.COM 			break;
18219585STim.Szeto@Sun.COM 	}
18229585STim.Szeto@Sun.COM }
18239585STim.Szeto@Sun.COM 
18249585STim.Szeto@Sun.COM static int
18259585STim.Szeto@Sun.COM modifyDiskLu(diskResource *disk, stmfGuid *luGuid, const char *fname)
18269585STim.Szeto@Sun.COM {
18279585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
18289585STim.Szeto@Sun.COM 	int luAliasLen = 0;
182910113SNattuvetty.Bhavyan@Sun.COM 	int luMgmtUrlLen = 0;
18309585STim.Szeto@Sun.COM 	int mluBufSize = 0;
18319585STim.Szeto@Sun.COM 	int bufOffset = 0;
18329585STim.Szeto@Sun.COM 	int fd = 0;
18339585STim.Szeto@Sun.COM 	int ioctlRet;
18349585STim.Szeto@Sun.COM 	int savedErrno;
18359585STim.Szeto@Sun.COM 	int fnameSize = 0;
18369585STim.Szeto@Sun.COM 	stmf_iocdata_t sbdIoctl = {0};
18379585STim.Szeto@Sun.COM 
18389585STim.Szeto@Sun.COM 	sbd_modify_lu_t *sbdLu = NULL;
18399585STim.Szeto@Sun.COM 
18409585STim.Szeto@Sun.COM 	if (luGuid == NULL && fname == NULL) {
18419585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
18429585STim.Szeto@Sun.COM 	}
18439585STim.Szeto@Sun.COM 
18449585STim.Szeto@Sun.COM 	if (fname) {
18459585STim.Szeto@Sun.COM 		fnameSize = strlen(fname) + 1;
18469585STim.Szeto@Sun.COM 		mluBufSize += fnameSize;
18479585STim.Szeto@Sun.COM 	}
18489585STim.Szeto@Sun.COM 
18499585STim.Szeto@Sun.COM 	/*
18509585STim.Szeto@Sun.COM 	 * Open control node for sbd
18519585STim.Szeto@Sun.COM 	 */
18529585STim.Szeto@Sun.COM 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
18539585STim.Szeto@Sun.COM 		return (ret);
18549585STim.Szeto@Sun.COM 
18559585STim.Szeto@Sun.COM 	if (disk->luAliasValid) {
18569585STim.Szeto@Sun.COM 		luAliasLen = strlen(disk->luAlias);
18579585STim.Szeto@Sun.COM 		mluBufSize += luAliasLen + 1;
18589585STim.Szeto@Sun.COM 	}
18599585STim.Szeto@Sun.COM 
186010113SNattuvetty.Bhavyan@Sun.COM 	if (disk->luMgmtUrlValid) {
186110113SNattuvetty.Bhavyan@Sun.COM 		luMgmtUrlLen = strlen(disk->luMgmtUrl);
186210113SNattuvetty.Bhavyan@Sun.COM 		mluBufSize += luMgmtUrlLen + 1;
186310113SNattuvetty.Bhavyan@Sun.COM 	}
186410113SNattuvetty.Bhavyan@Sun.COM 
18659585STim.Szeto@Sun.COM 	/*
18669585STim.Szeto@Sun.COM 	 * 8 is the size of the buffer set aside for
18679585STim.Szeto@Sun.COM 	 * concatenation of variable length fields
18689585STim.Szeto@Sun.COM 	 */
18699585STim.Szeto@Sun.COM 	sbdLu = (sbd_modify_lu_t *)calloc(1,
18709585STim.Szeto@Sun.COM 	    sizeof (sbd_modify_lu_t) + mluBufSize - 8 + fnameSize);
18719585STim.Szeto@Sun.COM 	if (sbdLu == NULL) {
18729585STim.Szeto@Sun.COM 		(void) close(fd);
18739585STim.Szeto@Sun.COM 		return (STMF_ERROR_NOMEM);
18749585STim.Szeto@Sun.COM 	}
18759585STim.Szeto@Sun.COM 
18769585STim.Szeto@Sun.COM 	sbdLu->mlu_struct_size = sizeof (sbd_modify_lu_t) +
18779585STim.Szeto@Sun.COM 	    mluBufSize - 8 + fnameSize;
18789585STim.Szeto@Sun.COM 
18799585STim.Szeto@Sun.COM 	if (disk->luAliasValid) {
18809585STim.Szeto@Sun.COM 		sbdLu->mlu_alias_valid = 1;
18819585STim.Szeto@Sun.COM 		sbdLu->mlu_alias_off = bufOffset;
18829585STim.Szeto@Sun.COM 		bcopy(disk->luAlias, &(sbdLu->mlu_buf[bufOffset]),
18839585STim.Szeto@Sun.COM 		    luAliasLen + 1);
18849585STim.Szeto@Sun.COM 		bufOffset += luAliasLen + 1;
18859585STim.Szeto@Sun.COM 	}
18869585STim.Szeto@Sun.COM 
188710113SNattuvetty.Bhavyan@Sun.COM 	if (disk->luMgmtUrlValid) {
188810113SNattuvetty.Bhavyan@Sun.COM 		sbdLu->mlu_mgmt_url_valid = 1;
188910113SNattuvetty.Bhavyan@Sun.COM 		sbdLu->mlu_mgmt_url_off = bufOffset;
189010113SNattuvetty.Bhavyan@Sun.COM 		bcopy(disk->luMgmtUrl, &(sbdLu->mlu_buf[bufOffset]),
189110113SNattuvetty.Bhavyan@Sun.COM 		    luMgmtUrlLen + 1);
189210113SNattuvetty.Bhavyan@Sun.COM 		bufOffset += luMgmtUrlLen + 1;
189310113SNattuvetty.Bhavyan@Sun.COM 	}
189410113SNattuvetty.Bhavyan@Sun.COM 
18959585STim.Szeto@Sun.COM 	if (disk->luSizeValid) {
18969585STim.Szeto@Sun.COM 		sbdLu->mlu_lu_size_valid = 1;
18979585STim.Szeto@Sun.COM 		sbdLu->mlu_lu_size = disk->luSize;
18989585STim.Szeto@Sun.COM 	}
18999585STim.Szeto@Sun.COM 
19009585STim.Szeto@Sun.COM 	if (disk->writeProtectEnableValid) {
19019585STim.Szeto@Sun.COM 		sbdLu->mlu_write_protected_valid = 1;
19029585STim.Szeto@Sun.COM 		if (disk->writeProtectEnable) {
19039585STim.Szeto@Sun.COM 			sbdLu->mlu_write_protected = 1;
19049585STim.Szeto@Sun.COM 		}
19059585STim.Szeto@Sun.COM 	}
19069585STim.Szeto@Sun.COM 
19079585STim.Szeto@Sun.COM 	if (disk->writebackCacheDisableValid) {
19089585STim.Szeto@Sun.COM 		sbdLu->mlu_writeback_cache_disable_valid = 1;
19099585STim.Szeto@Sun.COM 		if (disk->writebackCacheDisable) {
19109585STim.Szeto@Sun.COM 			sbdLu->mlu_writeback_cache_disable = 1;
19119585STim.Szeto@Sun.COM 		}
19129585STim.Szeto@Sun.COM 	}
19139585STim.Szeto@Sun.COM 
19149585STim.Szeto@Sun.COM 	if (luGuid) {
19159585STim.Szeto@Sun.COM 		bcopy(luGuid, sbdLu->mlu_input_guid, sizeof (stmfGuid));
19169585STim.Szeto@Sun.COM 		sbdLu->mlu_by_guid = 1;
19179585STim.Szeto@Sun.COM 	} else {
19189585STim.Szeto@Sun.COM 		sbdLu->mlu_fname_off = bufOffset;
19199585STim.Szeto@Sun.COM 		bcopy(fname, &(sbdLu->mlu_buf[bufOffset]), fnameSize + 1);
19209585STim.Szeto@Sun.COM 		sbdLu->mlu_by_fname = 1;
19219585STim.Szeto@Sun.COM 	}
19229585STim.Szeto@Sun.COM 
19239585STim.Szeto@Sun.COM 	sbdIoctl.stmf_version = STMF_VERSION_1;
19249585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf_size = sbdLu->mlu_struct_size;
19259585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdLu;
19269585STim.Szeto@Sun.COM 
19279585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, SBD_IOCTL_MODIFY_LU, &sbdIoctl);
19289585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
19299585STim.Szeto@Sun.COM 		savedErrno = errno;
19309585STim.Szeto@Sun.COM 		switch (savedErrno) {
19319585STim.Szeto@Sun.COM 			case EBUSY:
19329585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
19339585STim.Szeto@Sun.COM 				break;
19349585STim.Szeto@Sun.COM 			case EPERM:
19359585STim.Szeto@Sun.COM 			case EACCES:
19369585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
19379585STim.Szeto@Sun.COM 				break;
19389585STim.Szeto@Sun.COM 			default:
19399585STim.Szeto@Sun.COM 				diskError(sbdIoctl.stmf_error, &ret);
19409585STim.Szeto@Sun.COM 				if (ret == STMF_STATUS_ERROR) {
19419585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
19429585STim.Szeto@Sun.COM 					"modifyDiskLu:ioctl "
19439585STim.Szeto@Sun.COM 					"error(%d) (%d) (%d)", ioctlRet,
19449585STim.Szeto@Sun.COM 					    sbdIoctl.stmf_error, savedErrno);
19459585STim.Szeto@Sun.COM 				}
19469585STim.Szeto@Sun.COM 				break;
19479585STim.Szeto@Sun.COM 		}
19489585STim.Szeto@Sun.COM 	}
19499585STim.Szeto@Sun.COM 
19509585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
19519585STim.Szeto@Sun.COM 		goto done;
19529585STim.Szeto@Sun.COM 	}
19539585STim.Szeto@Sun.COM 
19549585STim.Szeto@Sun.COM done:
19559585STim.Szeto@Sun.COM 	free(sbdLu);
19569585STim.Szeto@Sun.COM 	(void) close(fd);
19579585STim.Szeto@Sun.COM 	return (ret);
19589585STim.Szeto@Sun.COM }
19599585STim.Szeto@Sun.COM 
19609585STim.Szeto@Sun.COM /*
19619585STim.Szeto@Sun.COM  * removeGuidFromDiskStore
19629585STim.Szeto@Sun.COM  *
19639585STim.Szeto@Sun.COM  * Purpose: delete a logical unit from the sbd provider data
19649585STim.Szeto@Sun.COM  */
19659585STim.Szeto@Sun.COM static int
19669585STim.Szeto@Sun.COM removeGuidFromDiskStore(stmfGuid *guid)
19679585STim.Szeto@Sun.COM {
19689585STim.Szeto@Sun.COM 	return (persistDiskGuid(guid, NULL, B_FALSE));
19699585STim.Szeto@Sun.COM }
19709585STim.Szeto@Sun.COM 
19719585STim.Szeto@Sun.COM 
19729585STim.Szeto@Sun.COM /*
19739585STim.Szeto@Sun.COM  * addGuidToDiskStore
19749585STim.Szeto@Sun.COM  *
19759585STim.Szeto@Sun.COM  * Purpose: add a logical unit to the sbd provider data
19769585STim.Szeto@Sun.COM  */
19779585STim.Szeto@Sun.COM static int
19789585STim.Szeto@Sun.COM addGuidToDiskStore(stmfGuid *guid, char *filename)
19799585STim.Szeto@Sun.COM {
19809585STim.Szeto@Sun.COM 	return (persistDiskGuid(guid, filename, B_TRUE));
19819585STim.Szeto@Sun.COM }
19829585STim.Szeto@Sun.COM 
19839585STim.Szeto@Sun.COM 
19849585STim.Szeto@Sun.COM /*
19859585STim.Szeto@Sun.COM  * persistDiskGuid
19869585STim.Szeto@Sun.COM  *
19879585STim.Szeto@Sun.COM  * Purpose: Persist or unpersist a guid for the sbd provider data
19889585STim.Szeto@Sun.COM  *
19899585STim.Szeto@Sun.COM  */
19909585STim.Szeto@Sun.COM static int
19919585STim.Szeto@Sun.COM persistDiskGuid(stmfGuid *guid, char *filename, boolean_t persist)
19929585STim.Szeto@Sun.COM {
19939585STim.Szeto@Sun.COM 	char	    guidAsciiBuf[LU_ASCII_GUID_SIZE + 1] = {0};
19949585STim.Szeto@Sun.COM 	nvlist_t    *nvl = NULL;
19959585STim.Szeto@Sun.COM 
19969585STim.Szeto@Sun.COM 	uint64_t    setToken;
19979585STim.Szeto@Sun.COM 	boolean_t   retryGetProviderData = B_FALSE;
19989585STim.Szeto@Sun.COM 	boolean_t   newData = B_FALSE;
19999585STim.Szeto@Sun.COM 	int	    ret = STMF_STATUS_SUCCESS;
20009585STim.Szeto@Sun.COM 	int	    retryCnt = 0;
20019585STim.Szeto@Sun.COM 	int	    stmfRet;
20029585STim.Szeto@Sun.COM 
20039585STim.Szeto@Sun.COM 	/* if we're persisting a guid, there must be a filename */
20049585STim.Szeto@Sun.COM 	if (persist && !filename) {
20059585STim.Szeto@Sun.COM 		return (1);
20069585STim.Szeto@Sun.COM 	}
20079585STim.Szeto@Sun.COM 
20089585STim.Szeto@Sun.COM 	/* guid is stored in lowercase ascii hex */
20099585STim.Szeto@Sun.COM 	(void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf),
20109585STim.Szeto@Sun.COM 	    "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
20119585STim.Szeto@Sun.COM 	    "%02x%02x%02x%02x%02x%02x",
20129585STim.Szeto@Sun.COM 	    guid->guid[0], guid->guid[1], guid->guid[2], guid->guid[3],
20139585STim.Szeto@Sun.COM 	    guid->guid[4], guid->guid[5], guid->guid[6], guid->guid[7],
20149585STim.Szeto@Sun.COM 	    guid->guid[8], guid->guid[9], guid->guid[10], guid->guid[11],
20159585STim.Szeto@Sun.COM 	    guid->guid[12], guid->guid[13], guid->guid[14], guid->guid[15]);
20169585STim.Szeto@Sun.COM 
20179585STim.Szeto@Sun.COM 
20189585STim.Szeto@Sun.COM 	do {
20199585STim.Szeto@Sun.COM 		retryGetProviderData = B_FALSE;
20209585STim.Szeto@Sun.COM 		stmfRet = stmfGetProviderDataProt("sbd", &nvl,
20219585STim.Szeto@Sun.COM 		    STMF_LU_PROVIDER_TYPE, &setToken);
20229585STim.Szeto@Sun.COM 		if (stmfRet != STMF_STATUS_SUCCESS) {
20239585STim.Szeto@Sun.COM 			if (persist && stmfRet == STMF_ERROR_NOT_FOUND) {
20249585STim.Szeto@Sun.COM 				ret = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0);
20259585STim.Szeto@Sun.COM 				if (ret != 0) {
20269585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
20279585STim.Szeto@Sun.COM 					    "unpersistGuid:nvlist_alloc(%d)",
20289585STim.Szeto@Sun.COM 					    ret);
20299585STim.Szeto@Sun.COM 					ret = STMF_STATUS_ERROR;
20309585STim.Szeto@Sun.COM 					goto done;
20319585STim.Szeto@Sun.COM 				}
20329585STim.Szeto@Sun.COM 				newData = B_TRUE;
20339585STim.Szeto@Sun.COM 			} else {
203410725SJohn.Forte@Sun.COM 				/*
203510725SJohn.Forte@Sun.COM 				 * if we're persisting the data, it's
203610725SJohn.Forte@Sun.COM 				 * an error. Otherwise, just return
203710725SJohn.Forte@Sun.COM 				 */
203810725SJohn.Forte@Sun.COM 				if (persist) {
203910725SJohn.Forte@Sun.COM 					ret = stmfRet;
204010725SJohn.Forte@Sun.COM 				}
20419585STim.Szeto@Sun.COM 				goto done;
20429585STim.Szeto@Sun.COM 			}
20439585STim.Szeto@Sun.COM 		}
20449585STim.Szeto@Sun.COM 		if (persist) {
20459585STim.Szeto@Sun.COM 			ret = nvlist_add_string(nvl, guidAsciiBuf, filename);
20469585STim.Szeto@Sun.COM 		} else {
20479585STim.Szeto@Sun.COM 			ret = nvlist_remove(nvl, guidAsciiBuf,
20489585STim.Szeto@Sun.COM 			    DATA_TYPE_STRING);
20499585STim.Szeto@Sun.COM 			if (ret == ENOENT) {
20509585STim.Szeto@Sun.COM 				ret = 0;
20519585STim.Szeto@Sun.COM 			}
20529585STim.Szeto@Sun.COM 		}
20539585STim.Szeto@Sun.COM 		if (ret == 0) {
20549585STim.Szeto@Sun.COM 			if (newData) {
20559585STim.Szeto@Sun.COM 				stmfRet = stmfSetProviderDataProt("sbd", nvl,
20569585STim.Szeto@Sun.COM 				    STMF_LU_PROVIDER_TYPE, NULL);
20579585STim.Szeto@Sun.COM 			} else {
20589585STim.Szeto@Sun.COM 				stmfRet = stmfSetProviderDataProt("sbd", nvl,
20599585STim.Szeto@Sun.COM 				    STMF_LU_PROVIDER_TYPE, &setToken);
20609585STim.Szeto@Sun.COM 			}
20619585STim.Szeto@Sun.COM 			if (stmfRet != STMF_STATUS_SUCCESS) {
20629585STim.Szeto@Sun.COM 				if (stmfRet == STMF_ERROR_BUSY) {
20639585STim.Szeto@Sun.COM 					/* get/set failed, try again */
20649585STim.Szeto@Sun.COM 					retryGetProviderData = B_TRUE;
20659585STim.Szeto@Sun.COM 					if (retryCnt++ > MAX_PROVIDER_RETRY) {
20669585STim.Szeto@Sun.COM 						ret = stmfRet;
20679585STim.Szeto@Sun.COM 						break;
20689585STim.Szeto@Sun.COM 					}
20699585STim.Szeto@Sun.COM 					continue;
20709585STim.Szeto@Sun.COM 				} else if (stmfRet ==
20719585STim.Szeto@Sun.COM 				    STMF_ERROR_PROV_DATA_STALE) {
20729585STim.Szeto@Sun.COM 					/* update failed, try again */
20739585STim.Szeto@Sun.COM 					nvlist_free(nvl);
20749585STim.Szeto@Sun.COM 					nvl = NULL;
20759585STim.Szeto@Sun.COM 					retryGetProviderData = B_TRUE;
20769585STim.Szeto@Sun.COM 					if (retryCnt++ > MAX_PROVIDER_RETRY) {
20779585STim.Szeto@Sun.COM 						ret = stmfRet;
20789585STim.Szeto@Sun.COM 						break;
20799585STim.Szeto@Sun.COM 					}
20809585STim.Szeto@Sun.COM 					continue;
20819585STim.Szeto@Sun.COM 				} else {
20829585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
20839585STim.Szeto@Sun.COM 					    "unpersistGuid:error(%x)", stmfRet);
20849585STim.Szeto@Sun.COM 					ret = stmfRet;
20859585STim.Szeto@Sun.COM 				}
20869585STim.Szeto@Sun.COM 				break;
20879585STim.Szeto@Sun.COM 			}
20889585STim.Szeto@Sun.COM 		} else {
20899585STim.Szeto@Sun.COM 			syslog(LOG_DEBUG,
20909585STim.Szeto@Sun.COM 			    "unpersistGuid:error nvlist_add/remove(%d)",
20919585STim.Szeto@Sun.COM 			    ret);
20929585STim.Szeto@Sun.COM 			ret = STMF_STATUS_ERROR;
20939585STim.Szeto@Sun.COM 		}
20949585STim.Szeto@Sun.COM 	} while (retryGetProviderData);
20959585STim.Szeto@Sun.COM 
20969585STim.Szeto@Sun.COM done:
20979585STim.Szeto@Sun.COM 	nvlist_free(nvl);
20989585STim.Szeto@Sun.COM 	return (ret);
20999585STim.Szeto@Sun.COM }
21009585STim.Szeto@Sun.COM 
21019585STim.Szeto@Sun.COM 
21029585STim.Szeto@Sun.COM /*
21039585STim.Szeto@Sun.COM  * stmfGetLuProp
21049585STim.Szeto@Sun.COM  *
21059585STim.Szeto@Sun.COM  * Purpose: Get current value for a resource property
21069585STim.Szeto@Sun.COM  *
21079585STim.Szeto@Sun.COM  * hdl - luResource from a previous call to stmfCreateLuResource
21089585STim.Szeto@Sun.COM  *
21099585STim.Szeto@Sun.COM  * resourceProp - a valid resource property type
21109585STim.Szeto@Sun.COM  *
21119585STim.Szeto@Sun.COM  * propVal - void pointer to a pointer of the value to be retrieved
21129585STim.Szeto@Sun.COM  */
21139585STim.Szeto@Sun.COM int
21149585STim.Szeto@Sun.COM stmfGetLuProp(luResource hdl, uint32_t prop, char *propVal, size_t *propLen)
21159585STim.Szeto@Sun.COM {
21169585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
21179585STim.Szeto@Sun.COM 	luResourceImpl *luPropsHdl = hdl;
21189585STim.Szeto@Sun.COM 	if (hdl == NULL || propLen == NULL || propVal == NULL) {
21199585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
21209585STim.Szeto@Sun.COM 	}
21219585STim.Szeto@Sun.COM 
21229585STim.Szeto@Sun.COM 	if (luPropsHdl->type == STMF_DISK) {
21239585STim.Szeto@Sun.COM 		ret = getDiskProp(luPropsHdl, prop, propVal, propLen);
21249585STim.Szeto@Sun.COM 	} else {
21259585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
21269585STim.Szeto@Sun.COM 	}
21279585STim.Szeto@Sun.COM 
21289585STim.Szeto@Sun.COM 	return (ret);
21299585STim.Szeto@Sun.COM }
21309585STim.Szeto@Sun.COM 
21319585STim.Szeto@Sun.COM /*
21329585STim.Szeto@Sun.COM  * stmfGetLuResource
21339585STim.Szeto@Sun.COM  *
21349585STim.Szeto@Sun.COM  * Purpose: Get a logical unit resource handle for a given logical unit.
21359585STim.Szeto@Sun.COM  *
21369585STim.Szeto@Sun.COM  * hdl - pointer to luResource
21379585STim.Szeto@Sun.COM  */
21389585STim.Szeto@Sun.COM int
21399585STim.Szeto@Sun.COM stmfGetLuResource(stmfGuid *luGuid, luResource *hdl)
21409585STim.Szeto@Sun.COM {
21419585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
21429585STim.Szeto@Sun.COM 	stmfLogicalUnitProperties luProps;
21439585STim.Szeto@Sun.COM 
2144*11691SSrivijitha.Dugganapalli@Sun.COM 	if (hdl == NULL) {
2145*11691SSrivijitha.Dugganapalli@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
2146*11691SSrivijitha.Dugganapalli@Sun.COM 	}
21479585STim.Szeto@Sun.COM 
21489585STim.Szeto@Sun.COM 	/* Check logical unit provider name to call correct dtype function */
21499585STim.Szeto@Sun.COM 	if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps))
21509585STim.Szeto@Sun.COM 	    != STMF_STATUS_SUCCESS) {
21519585STim.Szeto@Sun.COM 		return (ret);
21529585STim.Szeto@Sun.COM 	} else {
21539585STim.Szeto@Sun.COM 		if (strcmp(luProps.providerName, "sbd") == 0) {
21549585STim.Szeto@Sun.COM 			ret = getDiskAllProps(luGuid, hdl);
21559585STim.Szeto@Sun.COM 		} else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) {
21569585STim.Szeto@Sun.COM 			return (STMF_ERROR_NOT_FOUND);
21579585STim.Szeto@Sun.COM 		} else {
21589585STim.Szeto@Sun.COM 			return (STMF_ERROR_INVALID_ARG);
21599585STim.Szeto@Sun.COM 		}
21609585STim.Szeto@Sun.COM 	}
21619585STim.Szeto@Sun.COM 
21629585STim.Szeto@Sun.COM 	return (ret);
21639585STim.Szeto@Sun.COM }
21649585STim.Szeto@Sun.COM 
21659585STim.Szeto@Sun.COM /*
21669585STim.Szeto@Sun.COM  * getDiskAllProps
21679585STim.Szeto@Sun.COM  *
21689585STim.Szeto@Sun.COM  * Purpose: load all disk properties from sbd driver
21699585STim.Szeto@Sun.COM  *
21709585STim.Szeto@Sun.COM  * luGuid - guid of disk device for which properties are to be retrieved
21719585STim.Szeto@Sun.COM  * hdl - allocated luResource into which properties are to be copied
21729585STim.Szeto@Sun.COM  *
21739585STim.Szeto@Sun.COM  */
21749585STim.Szeto@Sun.COM static int
21759585STim.Szeto@Sun.COM getDiskAllProps(stmfGuid *luGuid, luResource *hdl)
21769585STim.Szeto@Sun.COM {
21779585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
21789585STim.Szeto@Sun.COM 	int fd;
21799585STim.Szeto@Sun.COM 	sbd_lu_props_t *sbdProps;
21809585STim.Szeto@Sun.COM 	int ioctlRet;
21819585STim.Szeto@Sun.COM 	int savedErrno;
21829585STim.Szeto@Sun.COM 	int sbdPropsSize = sizeof (*sbdProps) + MAX_SBD_PROPS;
21839585STim.Szeto@Sun.COM 	stmf_iocdata_t sbdIoctl = {0};
21849585STim.Szeto@Sun.COM 
21859585STim.Szeto@Sun.COM 	/*
21869585STim.Szeto@Sun.COM 	 * Open control node for sbd
21879585STim.Szeto@Sun.COM 	 */
21889585STim.Szeto@Sun.COM 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
21899585STim.Szeto@Sun.COM 		return (ret);
21909585STim.Szeto@Sun.COM 
21919585STim.Szeto@Sun.COM 
21929585STim.Szeto@Sun.COM 	*hdl = calloc(1, sizeof (luResourceImpl));
21939585STim.Szeto@Sun.COM 	if (*hdl == NULL) {
21949585STim.Szeto@Sun.COM 		(void) close(fd);
21959585STim.Szeto@Sun.COM 		return (STMF_ERROR_NOMEM);
21969585STim.Szeto@Sun.COM 	}
21979585STim.Szeto@Sun.COM 
21989585STim.Szeto@Sun.COM 	sbdProps = calloc(1, sbdPropsSize);
21999585STim.Szeto@Sun.COM 	if (sbdProps == NULL) {
22009585STim.Szeto@Sun.COM 		free(*hdl);
22019585STim.Szeto@Sun.COM 		(void) close(fd);
22029585STim.Szeto@Sun.COM 		return (STMF_ERROR_NOMEM);
22039585STim.Szeto@Sun.COM 	}
22049585STim.Szeto@Sun.COM 
22059585STim.Szeto@Sun.COM 	ret = createDiskResource((luResourceImpl *)*hdl);
22069585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
22079585STim.Szeto@Sun.COM 		free(*hdl);
220810725SJohn.Forte@Sun.COM 		free(sbdProps);
22099585STim.Szeto@Sun.COM 		(void) close(fd);
22109585STim.Szeto@Sun.COM 		return (ret);
22119585STim.Szeto@Sun.COM 	}
22129585STim.Szeto@Sun.COM 
22139585STim.Szeto@Sun.COM 	sbdProps->slp_input_guid = 1;
22149585STim.Szeto@Sun.COM 	bcopy(luGuid, sbdProps->slp_guid, sizeof (sbdProps->slp_guid));
22159585STim.Szeto@Sun.COM 
22169585STim.Szeto@Sun.COM 	sbdIoctl.stmf_version = STMF_VERSION_1;
22179585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf_size = sbdPropsSize;
22189585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdProps;
22199585STim.Szeto@Sun.COM 	sbdIoctl.stmf_obuf_size = sbdPropsSize;
22209585STim.Szeto@Sun.COM 	sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdProps;
22219585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, SBD_IOCTL_GET_LU_PROPS, &sbdIoctl);
22229585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
22239585STim.Szeto@Sun.COM 		savedErrno = errno;
22249585STim.Szeto@Sun.COM 		switch (savedErrno) {
22259585STim.Szeto@Sun.COM 			case EBUSY:
22269585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
22279585STim.Szeto@Sun.COM 				break;
22289585STim.Szeto@Sun.COM 			case EPERM:
22299585STim.Szeto@Sun.COM 			case EACCES:
22309585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
22319585STim.Szeto@Sun.COM 				break;
22329585STim.Szeto@Sun.COM 			case ENOENT:
22339585STim.Szeto@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
22349585STim.Szeto@Sun.COM 				break;
22359585STim.Szeto@Sun.COM 			default:
22369585STim.Szeto@Sun.COM 				syslog(LOG_DEBUG,
22379585STim.Szeto@Sun.COM 				    "getDiskAllProps:ioctl error(%d) (%d) (%d)",
22389585STim.Szeto@Sun.COM 				    ioctlRet, sbdIoctl.stmf_error, savedErrno);
22399585STim.Szeto@Sun.COM 				ret = STMF_STATUS_ERROR;
22409585STim.Szeto@Sun.COM 				break;
22419585STim.Szeto@Sun.COM 		}
22429585STim.Szeto@Sun.COM 	}
22439585STim.Szeto@Sun.COM 
22449585STim.Szeto@Sun.COM 	if (ret == STMF_STATUS_SUCCESS) {
22459585STim.Szeto@Sun.COM 		ret = loadDiskPropsFromDriver((luResourceImpl *)*hdl, sbdProps);
22469585STim.Szeto@Sun.COM 	}
22479585STim.Szeto@Sun.COM 
224810725SJohn.Forte@Sun.COM 	free(sbdProps);
22499585STim.Szeto@Sun.COM 	(void) close(fd);
22509585STim.Szeto@Sun.COM 	return (ret);
22519585STim.Szeto@Sun.COM }
22529585STim.Szeto@Sun.COM 
22539585STim.Szeto@Sun.COM /*
22549585STim.Szeto@Sun.COM  * loadDiskPropsFromDriver
22559585STim.Szeto@Sun.COM  *
22569585STim.Szeto@Sun.COM  * Purpose: Retrieve all disk type properties from sbd driver
22579585STim.Szeto@Sun.COM  *
22589585STim.Szeto@Sun.COM  * hdl - Allocated luResourceImpl
22599585STim.Szeto@Sun.COM  * sbdProps - sbd_lu_props_t structure returned from sbd driver
22609585STim.Szeto@Sun.COM  *
22619585STim.Szeto@Sun.COM  */
22629585STim.Szeto@Sun.COM static int
22639585STim.Szeto@Sun.COM loadDiskPropsFromDriver(luResourceImpl *hdl, sbd_lu_props_t *sbdProps)
22649585STim.Szeto@Sun.COM {
22659585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
22669585STim.Szeto@Sun.COM 	diskResource *diskLu = hdl->resource;
22679585STim.Szeto@Sun.COM 	/* copy guid */
22689585STim.Szeto@Sun.COM 	diskLu->luGuidValid = B_TRUE;
22699585STim.Szeto@Sun.COM 	bcopy(sbdProps->slp_guid, diskLu->luGuid, sizeof (sbdProps->slp_guid));
22709585STim.Szeto@Sun.COM 
22719585STim.Szeto@Sun.COM 	if (sbdProps->slp_separate_meta && sbdProps->slp_meta_fname_valid) {
22729585STim.Szeto@Sun.COM 		diskLu->luMetaFileNameValid = B_TRUE;
22739585STim.Szeto@Sun.COM 		if (strlcpy(diskLu->luMetaFileName,
22749585STim.Szeto@Sun.COM 		    (char *)&(sbdProps->slp_buf[sbdProps->slp_meta_fname_off]),
22759585STim.Szeto@Sun.COM 		    sizeof (diskLu->luMetaFileName)) >=
22769585STim.Szeto@Sun.COM 		    sizeof (diskLu->luMetaFileName)) {
22779585STim.Szeto@Sun.COM 			return (STMF_STATUS_ERROR);
22789585STim.Szeto@Sun.COM 		}
22799585STim.Szeto@Sun.COM 	}
22809585STim.Szeto@Sun.COM 
22819585STim.Szeto@Sun.COM 	if (sbdProps->slp_data_fname_valid) {
22829585STim.Szeto@Sun.COM 		diskLu->luDataFileNameValid = B_TRUE;
22839585STim.Szeto@Sun.COM 		if (strlcpy(diskLu->luDataFileName,
22849585STim.Szeto@Sun.COM 		    (char *)&(sbdProps->slp_buf[sbdProps->slp_data_fname_off]),
22859585STim.Szeto@Sun.COM 		    sizeof (diskLu->luDataFileName)) >=
22869585STim.Szeto@Sun.COM 		    sizeof (diskLu->luDataFileName)) {
22879585STim.Szeto@Sun.COM 			return (STMF_STATUS_ERROR);
22889585STim.Szeto@Sun.COM 		}
22899585STim.Szeto@Sun.COM 	}
22909585STim.Szeto@Sun.COM 
22919585STim.Szeto@Sun.COM 	if (sbdProps->slp_serial_valid) {
22929585STim.Szeto@Sun.COM 		diskLu->serialNumValid = B_TRUE;
22939585STim.Szeto@Sun.COM 		bcopy(&(sbdProps->slp_buf[sbdProps->slp_serial_off]),
22949585STim.Szeto@Sun.COM 		    diskLu->serialNum, sbdProps->slp_serial_size);
22959585STim.Szeto@Sun.COM 	}
22969585STim.Szeto@Sun.COM 
229710113SNattuvetty.Bhavyan@Sun.COM 	if (sbdProps->slp_mgmt_url_valid) {
229810113SNattuvetty.Bhavyan@Sun.COM 		diskLu->luMgmtUrlValid = B_TRUE;
229910113SNattuvetty.Bhavyan@Sun.COM 		if (strlcpy(diskLu->luMgmtUrl,
230010113SNattuvetty.Bhavyan@Sun.COM 		    (char *)&(sbdProps->slp_buf[sbdProps->slp_mgmt_url_off]),
230110113SNattuvetty.Bhavyan@Sun.COM 		    sizeof (diskLu->luMgmtUrl)) >=
230210113SNattuvetty.Bhavyan@Sun.COM 		    sizeof (diskLu->luMgmtUrl)) {
230310113SNattuvetty.Bhavyan@Sun.COM 			return (STMF_STATUS_ERROR);
230410113SNattuvetty.Bhavyan@Sun.COM 		}
230510113SNattuvetty.Bhavyan@Sun.COM 	}
230610113SNattuvetty.Bhavyan@Sun.COM 
23079585STim.Szeto@Sun.COM 	if (sbdProps->slp_alias_valid) {
23089585STim.Szeto@Sun.COM 		diskLu->luAliasValid = B_TRUE;
23099585STim.Szeto@Sun.COM 		if (strlcpy(diskLu->luAlias,
23109585STim.Szeto@Sun.COM 		    (char *)&(sbdProps->slp_buf[sbdProps->slp_alias_off]),
23119585STim.Szeto@Sun.COM 		    sizeof (diskLu->luAlias)) >=
23129585STim.Szeto@Sun.COM 		    sizeof (diskLu->luAlias)) {
23139585STim.Szeto@Sun.COM 			return (STMF_STATUS_ERROR);
23149585STim.Szeto@Sun.COM 		}
23159585STim.Szeto@Sun.COM 	} else { /* set alias to data filename if not set */
23169585STim.Szeto@Sun.COM 		if (sbdProps->slp_data_fname_valid) {
23179585STim.Szeto@Sun.COM 			diskLu->luAliasValid = B_TRUE;
23189585STim.Szeto@Sun.COM 			if (strlcpy(diskLu->luAlias,
23199585STim.Szeto@Sun.COM 			    (char *)&(sbdProps->slp_buf[
23209585STim.Szeto@Sun.COM 			    sbdProps->slp_data_fname_off]),
23219585STim.Szeto@Sun.COM 			    sizeof (diskLu->luAlias)) >=
23229585STim.Szeto@Sun.COM 			    sizeof (diskLu->luAlias)) {
23239585STim.Szeto@Sun.COM 				return (STMF_STATUS_ERROR);
23249585STim.Szeto@Sun.COM 			}
23259585STim.Szeto@Sun.COM 		}
23269585STim.Szeto@Sun.COM 	}
23279585STim.Szeto@Sun.COM 
23289585STim.Szeto@Sun.COM 	diskLu->vidValid = B_TRUE;
23299585STim.Szeto@Sun.COM 	bcopy(sbdProps->slp_vid, diskLu->vid, sizeof (diskLu->vid));
23309585STim.Szeto@Sun.COM 
23319585STim.Szeto@Sun.COM 	diskLu->pidValid = B_TRUE;
23329585STim.Szeto@Sun.COM 	bcopy(sbdProps->slp_pid, diskLu->pid, sizeof (diskLu->pid));
23339585STim.Szeto@Sun.COM 
23349585STim.Szeto@Sun.COM 	diskLu->revValid = B_TRUE;
23359585STim.Szeto@Sun.COM 	bcopy(sbdProps->slp_rev, diskLu->rev, sizeof (diskLu->rev));
23369585STim.Szeto@Sun.COM 
23379585STim.Szeto@Sun.COM 	diskLu->writeProtectEnableValid = B_TRUE;
23389585STim.Szeto@Sun.COM 	if (sbdProps->slp_write_protected) {
23399585STim.Szeto@Sun.COM 		diskLu->writeProtectEnable = B_TRUE;
23409585STim.Szeto@Sun.COM 	}
23419585STim.Szeto@Sun.COM 
23429585STim.Szeto@Sun.COM 	diskLu->writebackCacheDisableValid = B_TRUE;
23439585STim.Szeto@Sun.COM 	if (sbdProps->slp_writeback_cache_disable_cur) {
23449585STim.Szeto@Sun.COM 		diskLu->writebackCacheDisable = B_TRUE;
23459585STim.Szeto@Sun.COM 	}
23469585STim.Szeto@Sun.COM 
23479585STim.Szeto@Sun.COM 	diskLu->blkSizeValid = B_TRUE;
23489585STim.Szeto@Sun.COM 	diskLu->blkSize = sbdProps->slp_blksize;
23499585STim.Szeto@Sun.COM 
23509585STim.Szeto@Sun.COM 	diskLu->luSizeValid = B_TRUE;
23519585STim.Szeto@Sun.COM 	diskLu->luSize = sbdProps->slp_lu_size;
23529585STim.Szeto@Sun.COM 
235310725SJohn.Forte@Sun.COM 	diskLu->accessState = sbdProps->slp_access_state;
235410725SJohn.Forte@Sun.COM 
23559585STim.Szeto@Sun.COM 	return (ret);
23569585STim.Szeto@Sun.COM }
23579585STim.Szeto@Sun.COM 
235811103SJohn.Forte@Sun.COM /*
235911103SJohn.Forte@Sun.COM  * stmfGetGlobalLuProp
236011103SJohn.Forte@Sun.COM  *
236111103SJohn.Forte@Sun.COM  * Purpose: get a global property for a device type
236211103SJohn.Forte@Sun.COM  *
236311103SJohn.Forte@Sun.COM  */
236411103SJohn.Forte@Sun.COM int
236511103SJohn.Forte@Sun.COM stmfGetGlobalLuProp(uint16_t dType, uint32_t prop, char *propVal,
236611103SJohn.Forte@Sun.COM     size_t *propLen)
236711103SJohn.Forte@Sun.COM {
236811103SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
236911103SJohn.Forte@Sun.COM 	if (dType != STMF_DISK || propVal == NULL) {
237011103SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
237111103SJohn.Forte@Sun.COM 	}
237211103SJohn.Forte@Sun.COM 
237311103SJohn.Forte@Sun.COM 	ret = getDiskGlobalProp(prop, propVal, propLen);
237411103SJohn.Forte@Sun.COM 
237511103SJohn.Forte@Sun.COM 	return (ret);
237611103SJohn.Forte@Sun.COM }
237711103SJohn.Forte@Sun.COM 
237811103SJohn.Forte@Sun.COM /*
237911103SJohn.Forte@Sun.COM  * getDiskGlobalProp
238011103SJohn.Forte@Sun.COM  *
238111103SJohn.Forte@Sun.COM  * Purpose: get global property from sbd driver
238211103SJohn.Forte@Sun.COM  *
238311103SJohn.Forte@Sun.COM  */
238411103SJohn.Forte@Sun.COM static int
238511103SJohn.Forte@Sun.COM getDiskGlobalProp(uint32_t prop, char *propVal, size_t *propLen)
238611103SJohn.Forte@Sun.COM {
238711103SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
238811103SJohn.Forte@Sun.COM 	int fd;
238911103SJohn.Forte@Sun.COM 	sbd_global_props_t *sbdProps;
239011103SJohn.Forte@Sun.COM 	void *sbd_realloc;
239111103SJohn.Forte@Sun.COM 	int retryCnt = 0;
239211103SJohn.Forte@Sun.COM 	boolean_t retry;
239311103SJohn.Forte@Sun.COM 	int ioctlRet;
239411103SJohn.Forte@Sun.COM 	int savedErrno;
239511103SJohn.Forte@Sun.COM 	int sbdPropsSize = sizeof (*sbdProps) + MAX_SBD_PROPS;
239611103SJohn.Forte@Sun.COM 	stmf_iocdata_t sbdIoctl = {0};
239711103SJohn.Forte@Sun.COM 	size_t reqLen;
239811103SJohn.Forte@Sun.COM 
239911103SJohn.Forte@Sun.COM 	switch (prop) {
240011103SJohn.Forte@Sun.COM 		case STMF_LU_PROP_MGMT_URL:
240111103SJohn.Forte@Sun.COM 			break;
240211103SJohn.Forte@Sun.COM 		default:
240311103SJohn.Forte@Sun.COM 			return (STMF_ERROR_INVALID_PROP);
240411103SJohn.Forte@Sun.COM 	}
240511103SJohn.Forte@Sun.COM 
240611103SJohn.Forte@Sun.COM 	/*
240711103SJohn.Forte@Sun.COM 	 * Open control node for sbd
240811103SJohn.Forte@Sun.COM 	 */
240911103SJohn.Forte@Sun.COM 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
241011103SJohn.Forte@Sun.COM 		return (ret);
241111103SJohn.Forte@Sun.COM 
241211103SJohn.Forte@Sun.COM 	sbdProps = calloc(1, sbdPropsSize);
241311103SJohn.Forte@Sun.COM 	if (sbdProps == NULL) {
241411103SJohn.Forte@Sun.COM 		(void) close(fd);
241511103SJohn.Forte@Sun.COM 		return (STMF_ERROR_NOMEM);
241611103SJohn.Forte@Sun.COM 	}
241711103SJohn.Forte@Sun.COM 
241811103SJohn.Forte@Sun.COM 	do {
241911103SJohn.Forte@Sun.COM 		retry = B_FALSE;
242011103SJohn.Forte@Sun.COM 		sbdIoctl.stmf_version = STMF_VERSION_1;
242111103SJohn.Forte@Sun.COM 		sbdIoctl.stmf_obuf_size = sbdPropsSize;
242211103SJohn.Forte@Sun.COM 		sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdProps;
242311103SJohn.Forte@Sun.COM 		ioctlRet = ioctl(fd, SBD_IOCTL_GET_GLOBAL_LU, &sbdIoctl);
242411103SJohn.Forte@Sun.COM 		if (ioctlRet != 0) {
242511103SJohn.Forte@Sun.COM 			savedErrno = errno;
242611103SJohn.Forte@Sun.COM 			switch (savedErrno) {
242711103SJohn.Forte@Sun.COM 				case EBUSY:
242811103SJohn.Forte@Sun.COM 					ret = STMF_ERROR_BUSY;
242911103SJohn.Forte@Sun.COM 					break;
243011103SJohn.Forte@Sun.COM 				case EPERM:
243111103SJohn.Forte@Sun.COM 				case EACCES:
243211103SJohn.Forte@Sun.COM 					ret = STMF_ERROR_PERM;
243311103SJohn.Forte@Sun.COM 					break;
243411103SJohn.Forte@Sun.COM 				case ENOMEM:
243511103SJohn.Forte@Sun.COM 					if (sbdIoctl.stmf_error ==
243611103SJohn.Forte@Sun.COM 					    SBD_RET_INSUFFICIENT_BUF_SPACE &&
243711103SJohn.Forte@Sun.COM 					    retryCnt++ < 3) {
243811103SJohn.Forte@Sun.COM 						sbdPropsSize =
243911103SJohn.Forte@Sun.COM 						    sizeof (*sbdProps) +
244011103SJohn.Forte@Sun.COM 						    sbdProps->
244111103SJohn.Forte@Sun.COM 						    mlu_buf_size_needed;
244211103SJohn.Forte@Sun.COM 
244311103SJohn.Forte@Sun.COM 						sbd_realloc = sbdProps;
244411103SJohn.Forte@Sun.COM 						sbdProps = realloc(sbdProps,
244511103SJohn.Forte@Sun.COM 						    sbdPropsSize);
244611103SJohn.Forte@Sun.COM 						if (sbdProps == NULL) {
244711103SJohn.Forte@Sun.COM 							free(sbd_realloc);
244811103SJohn.Forte@Sun.COM 							ret = STMF_ERROR_NOMEM;
244911103SJohn.Forte@Sun.COM 							break;
245011103SJohn.Forte@Sun.COM 						}
245111103SJohn.Forte@Sun.COM 						retry = B_TRUE;
245211103SJohn.Forte@Sun.COM 					} else {
245311103SJohn.Forte@Sun.COM 						ret = STMF_ERROR_NOMEM;
245411103SJohn.Forte@Sun.COM 					}
245511103SJohn.Forte@Sun.COM 					break;
245611103SJohn.Forte@Sun.COM 				default:
245711103SJohn.Forte@Sun.COM 					syslog(LOG_DEBUG,
245811103SJohn.Forte@Sun.COM 					    "getDiskGlobalProp:ioctl error(%d)"
245911103SJohn.Forte@Sun.COM 					    "(%d)(%d)", ioctlRet,
246011103SJohn.Forte@Sun.COM 					    sbdIoctl.stmf_error, savedErrno);
246111103SJohn.Forte@Sun.COM 					ret = STMF_STATUS_ERROR;
246211103SJohn.Forte@Sun.COM 					break;
246311103SJohn.Forte@Sun.COM 			}
246411103SJohn.Forte@Sun.COM 
246511103SJohn.Forte@Sun.COM 		}
246611103SJohn.Forte@Sun.COM 	} while (retry);
246711103SJohn.Forte@Sun.COM 
246811103SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
246911103SJohn.Forte@Sun.COM 		goto done;
247011103SJohn.Forte@Sun.COM 	}
247111103SJohn.Forte@Sun.COM 
247211103SJohn.Forte@Sun.COM 	switch (prop) {
247311103SJohn.Forte@Sun.COM 		case STMF_LU_PROP_MGMT_URL:
247411103SJohn.Forte@Sun.COM 			if (sbdProps->mlu_mgmt_url_valid == 0) {
247511103SJohn.Forte@Sun.COM 				ret = STMF_ERROR_NO_PROP;
247611103SJohn.Forte@Sun.COM 				goto done;
247711103SJohn.Forte@Sun.COM 			}
247811103SJohn.Forte@Sun.COM 			if ((reqLen = strlcpy(propVal, (char *)&(
247911103SJohn.Forte@Sun.COM 			    sbdProps->mlu_buf[sbdProps->mlu_mgmt_url_off]),
248011103SJohn.Forte@Sun.COM 			    *propLen)) >= *propLen) {
248111103SJohn.Forte@Sun.COM 				*propLen = reqLen + 1;
248211103SJohn.Forte@Sun.COM 				ret = STMF_ERROR_INVALID_ARG;
248311103SJohn.Forte@Sun.COM 				goto done;
248411103SJohn.Forte@Sun.COM 			}
248511103SJohn.Forte@Sun.COM 			break;
248611103SJohn.Forte@Sun.COM 	}
248711103SJohn.Forte@Sun.COM 
248811103SJohn.Forte@Sun.COM done:
248911103SJohn.Forte@Sun.COM 	free(sbdProps);
249011103SJohn.Forte@Sun.COM 	(void) close(fd);
249111103SJohn.Forte@Sun.COM 	return (ret);
249211103SJohn.Forte@Sun.COM }
249311103SJohn.Forte@Sun.COM 
249411103SJohn.Forte@Sun.COM /*
249511103SJohn.Forte@Sun.COM  * stmfSetGlobalLuProp
249611103SJohn.Forte@Sun.COM  *
249711103SJohn.Forte@Sun.COM  * Purpose: set a global property for a device type
249811103SJohn.Forte@Sun.COM  *
249911103SJohn.Forte@Sun.COM  */
250011103SJohn.Forte@Sun.COM int
250111103SJohn.Forte@Sun.COM stmfSetGlobalLuProp(uint16_t dType, uint32_t prop, const char *propVal)
250211103SJohn.Forte@Sun.COM {
250311103SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
250411103SJohn.Forte@Sun.COM 	if (dType != STMF_DISK || propVal == NULL) {
250511103SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
250611103SJohn.Forte@Sun.COM 	}
250711103SJohn.Forte@Sun.COM 
250811103SJohn.Forte@Sun.COM 	ret = setDiskGlobalProp(prop, propVal);
250911103SJohn.Forte@Sun.COM 
251011103SJohn.Forte@Sun.COM 	return (ret);
251111103SJohn.Forte@Sun.COM }
251211103SJohn.Forte@Sun.COM 
251311103SJohn.Forte@Sun.COM /*
251411103SJohn.Forte@Sun.COM  * setDiskGlobalProp
251511103SJohn.Forte@Sun.COM  *
251611103SJohn.Forte@Sun.COM  * Purpose: set properties for resource of type disk
251711103SJohn.Forte@Sun.COM  *
251811103SJohn.Forte@Sun.COM  * resourceProp - valid resource identifier
251911103SJohn.Forte@Sun.COM  * propVal - valid resource value
252011103SJohn.Forte@Sun.COM  */
252111103SJohn.Forte@Sun.COM static int
252211103SJohn.Forte@Sun.COM setDiskGlobalProp(uint32_t resourceProp, const char *propVal)
252311103SJohn.Forte@Sun.COM {
252411103SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
252511103SJohn.Forte@Sun.COM 	sbd_global_props_t *sbdGlobalProps = NULL;
252611103SJohn.Forte@Sun.COM 	int sbdGlobalPropsSize = 0;
252711103SJohn.Forte@Sun.COM 	int propLen;
252811103SJohn.Forte@Sun.COM 	int mluBufSize = 0;
252911103SJohn.Forte@Sun.COM 	int fd;
253011103SJohn.Forte@Sun.COM 	int savedErrno;
253111103SJohn.Forte@Sun.COM 	int ioctlRet;
253211103SJohn.Forte@Sun.COM 	stmf_iocdata_t sbdIoctl = {0};
253311103SJohn.Forte@Sun.COM 
253411103SJohn.Forte@Sun.COM 	switch (resourceProp) {
253511103SJohn.Forte@Sun.COM 		case STMF_LU_PROP_MGMT_URL:
253611103SJohn.Forte@Sun.COM 			break;
253711103SJohn.Forte@Sun.COM 		default:
253811103SJohn.Forte@Sun.COM 			return (STMF_ERROR_INVALID_PROP);
253911103SJohn.Forte@Sun.COM 			break;
254011103SJohn.Forte@Sun.COM 	}
254111103SJohn.Forte@Sun.COM 
254211103SJohn.Forte@Sun.COM 	/*
254311103SJohn.Forte@Sun.COM 	 * Open control node for sbd
254411103SJohn.Forte@Sun.COM 	 */
254511103SJohn.Forte@Sun.COM 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
254611103SJohn.Forte@Sun.COM 		return (ret);
254711103SJohn.Forte@Sun.COM 
254811103SJohn.Forte@Sun.COM 	propLen = strlen(propVal);
254911103SJohn.Forte@Sun.COM 	mluBufSize += propLen + 1;
255011103SJohn.Forte@Sun.COM 	sbdGlobalPropsSize += sizeof (sbd_global_props_t) - 8 +
255111103SJohn.Forte@Sun.COM 	    max(8, mluBufSize);
255211103SJohn.Forte@Sun.COM 	/*
255311103SJohn.Forte@Sun.COM 	 * 8 is the size of the buffer set aside for
255411103SJohn.Forte@Sun.COM 	 * concatenation of variable length fields
255511103SJohn.Forte@Sun.COM 	 */
255611103SJohn.Forte@Sun.COM 	sbdGlobalProps = (sbd_global_props_t *)calloc(1, sbdGlobalPropsSize);
255711103SJohn.Forte@Sun.COM 	if (sbdGlobalProps == NULL) {
255811103SJohn.Forte@Sun.COM 		(void) close(fd);
255911103SJohn.Forte@Sun.COM 		return (STMF_ERROR_NOMEM);
256011103SJohn.Forte@Sun.COM 	}
256111103SJohn.Forte@Sun.COM 
256211103SJohn.Forte@Sun.COM 	sbdGlobalProps->mlu_struct_size = sbdGlobalPropsSize;
256311103SJohn.Forte@Sun.COM 
256411103SJohn.Forte@Sun.COM 	switch (resourceProp) {
256511103SJohn.Forte@Sun.COM 		case STMF_LU_PROP_MGMT_URL:
256611103SJohn.Forte@Sun.COM 			sbdGlobalProps->mlu_mgmt_url_valid = 1;
256711103SJohn.Forte@Sun.COM 			bcopy(propVal, &(sbdGlobalProps->mlu_buf),
256811103SJohn.Forte@Sun.COM 			    propLen + 1);
256911103SJohn.Forte@Sun.COM 			break;
257011103SJohn.Forte@Sun.COM 		default:
257111103SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NO_PROP;
257211103SJohn.Forte@Sun.COM 			goto done;
257311103SJohn.Forte@Sun.COM 	}
257411103SJohn.Forte@Sun.COM 
257511103SJohn.Forte@Sun.COM 	sbdIoctl.stmf_version = STMF_VERSION_1;
257611103SJohn.Forte@Sun.COM 	sbdIoctl.stmf_ibuf_size = sbdGlobalProps->mlu_struct_size;
257711103SJohn.Forte@Sun.COM 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdGlobalProps;
257811103SJohn.Forte@Sun.COM 
257911103SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, SBD_IOCTL_SET_GLOBAL_LU, &sbdIoctl);
258011103SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
258111103SJohn.Forte@Sun.COM 		savedErrno = errno;
258211103SJohn.Forte@Sun.COM 		switch (savedErrno) {
258311103SJohn.Forte@Sun.COM 			case EBUSY:
258411103SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
258511103SJohn.Forte@Sun.COM 				break;
258611103SJohn.Forte@Sun.COM 			case EPERM:
258711103SJohn.Forte@Sun.COM 			case EACCES:
258811103SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
258911103SJohn.Forte@Sun.COM 				break;
259011103SJohn.Forte@Sun.COM 			default:
259111103SJohn.Forte@Sun.COM 				diskError(sbdIoctl.stmf_error, &ret);
259211103SJohn.Forte@Sun.COM 				if (ret == STMF_STATUS_ERROR) {
259311103SJohn.Forte@Sun.COM 					syslog(LOG_DEBUG,
259411103SJohn.Forte@Sun.COM 					"modifyDiskLu:ioctl "
259511103SJohn.Forte@Sun.COM 					"error(%d) (%d) (%d)", ioctlRet,
259611103SJohn.Forte@Sun.COM 					    sbdIoctl.stmf_error, savedErrno);
259711103SJohn.Forte@Sun.COM 				}
259811103SJohn.Forte@Sun.COM 				break;
259911103SJohn.Forte@Sun.COM 		}
260011103SJohn.Forte@Sun.COM 	}
260111103SJohn.Forte@Sun.COM 
260211103SJohn.Forte@Sun.COM done:
260311103SJohn.Forte@Sun.COM 	free(sbdGlobalProps);
260411103SJohn.Forte@Sun.COM 	(void) close(fd);
260511103SJohn.Forte@Sun.COM 	return (ret);
260611103SJohn.Forte@Sun.COM }
260711103SJohn.Forte@Sun.COM 
26089585STim.Szeto@Sun.COM 
26099585STim.Szeto@Sun.COM /*
26109585STim.Szeto@Sun.COM  * stmfSetLuProp
26119585STim.Szeto@Sun.COM  *
26129585STim.Szeto@Sun.COM  * Purpose: set a property on an luResource
26139585STim.Szeto@Sun.COM  *
26149585STim.Szeto@Sun.COM  * hdl - allocated luResource
26159585STim.Szeto@Sun.COM  * prop - property identifier
26169585STim.Szeto@Sun.COM  * propVal - property value to be set
26179585STim.Szeto@Sun.COM  */
26189585STim.Szeto@Sun.COM int
26199585STim.Szeto@Sun.COM stmfSetLuProp(luResource hdl, uint32_t prop, const char *propVal)
26209585STim.Szeto@Sun.COM {
26219585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
26229585STim.Szeto@Sun.COM 	luResourceImpl *luPropsHdl = hdl;
26239585STim.Szeto@Sun.COM 	if (hdl == NULL) {
26249585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
26259585STim.Szeto@Sun.COM 	}
26269585STim.Szeto@Sun.COM 
26279585STim.Szeto@Sun.COM 	if (luPropsHdl->type == STMF_DISK) {
26289585STim.Szeto@Sun.COM 		ret = setDiskProp(luPropsHdl, prop, propVal);
26299585STim.Szeto@Sun.COM 	} else {
26309585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
26319585STim.Szeto@Sun.COM 	}
26329585STim.Szeto@Sun.COM 
26339585STim.Szeto@Sun.COM 	return (ret);
26349585STim.Szeto@Sun.COM }
26359585STim.Szeto@Sun.COM 
26369585STim.Szeto@Sun.COM /*
26379585STim.Szeto@Sun.COM  * getDiskProp
26389585STim.Szeto@Sun.COM  *
26399585STim.Szeto@Sun.COM  * Purpose: retrieve a given property from a logical unit resource of type disk
26409585STim.Szeto@Sun.COM  *
26419585STim.Szeto@Sun.COM  * hdl - allocated luResourceImpl
26429585STim.Szeto@Sun.COM  * prop - property identifier
26439585STim.Szeto@Sun.COM  * propVal - pointer to character to contain the retrieved property value
26449585STim.Szeto@Sun.COM  * propLen - On input this is the length of propVal. On failure, it contains the
26459585STim.Szeto@Sun.COM  *           number of bytes required for propVal
26469585STim.Szeto@Sun.COM  */
26479585STim.Szeto@Sun.COM static int
26489585STim.Szeto@Sun.COM getDiskProp(luResourceImpl *hdl, uint32_t prop, char *propVal, size_t *propLen)
26499585STim.Szeto@Sun.COM {
26509585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
26519585STim.Szeto@Sun.COM 	diskResource *diskLu = hdl->resource;
265210725SJohn.Forte@Sun.COM 	char accessState[20];
26539585STim.Szeto@Sun.COM 	size_t reqLen;
26549585STim.Szeto@Sun.COM 
265510725SJohn.Forte@Sun.COM 	if (prop == STMF_LU_PROP_ACCESS_STATE) {
265610725SJohn.Forte@Sun.COM 		if (diskLu->accessState == SBD_LU_ACTIVE) {
265710725SJohn.Forte@Sun.COM 			(void) strlcpy(accessState, STMF_ACCESS_ACTIVE,
265810725SJohn.Forte@Sun.COM 			    sizeof (accessState));
265910725SJohn.Forte@Sun.COM 		} else if (diskLu->accessState == SBD_LU_TRANSITION_TO_ACTIVE) {
266010725SJohn.Forte@Sun.COM 			(void) strlcpy(accessState,
266110725SJohn.Forte@Sun.COM 			    STMF_ACCESS_STANDBY_TO_ACTIVE,
266210725SJohn.Forte@Sun.COM 			    sizeof (accessState));
266310725SJohn.Forte@Sun.COM 		} else if (diskLu->accessState == SBD_LU_STANDBY) {
266410725SJohn.Forte@Sun.COM 			(void) strlcpy(accessState, STMF_ACCESS_STANDBY,
266510725SJohn.Forte@Sun.COM 			    sizeof (accessState));
266610725SJohn.Forte@Sun.COM 		} else if (diskLu->accessState ==
266710725SJohn.Forte@Sun.COM 		    SBD_LU_TRANSITION_TO_STANDBY) {
266810725SJohn.Forte@Sun.COM 			(void) strlcpy(accessState,
266910725SJohn.Forte@Sun.COM 			    STMF_ACCESS_ACTIVE_TO_STANDBY,
267010725SJohn.Forte@Sun.COM 			    sizeof (accessState));
267110725SJohn.Forte@Sun.COM 		}
267210725SJohn.Forte@Sun.COM 		if ((reqLen = strlcpy(propVal, accessState,
267310725SJohn.Forte@Sun.COM 		    *propLen)) >= *propLen) {
267410725SJohn.Forte@Sun.COM 			*propLen = reqLen + 1;
267510725SJohn.Forte@Sun.COM 			return (STMF_ERROR_INVALID_ARG);
267610725SJohn.Forte@Sun.COM 		}
267710725SJohn.Forte@Sun.COM 		return (0);
267810725SJohn.Forte@Sun.COM 	}
267910725SJohn.Forte@Sun.COM 
268010725SJohn.Forte@Sun.COM 	if (diskLu->accessState != SBD_LU_ACTIVE) {
268110725SJohn.Forte@Sun.COM 		return (STMF_ERROR_NO_PROP_STANDBY);
268210725SJohn.Forte@Sun.COM 	}
268310725SJohn.Forte@Sun.COM 
26849585STim.Szeto@Sun.COM 	switch (prop) {
26859585STim.Szeto@Sun.COM 		case STMF_LU_PROP_BLOCK_SIZE:
26869585STim.Szeto@Sun.COM 			if (diskLu->blkSizeValid == B_FALSE) {
26879585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
26889585STim.Szeto@Sun.COM 			}
26899585STim.Szeto@Sun.COM 			reqLen = snprintf(propVal, *propLen, "%llu",
26909585STim.Szeto@Sun.COM 			    (u_longlong_t)diskLu->blkSize);
26919585STim.Szeto@Sun.COM 			if (reqLen >= *propLen) {
26929585STim.Szeto@Sun.COM 				*propLen = reqLen + 1;
26939585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
26949585STim.Szeto@Sun.COM 			}
26959585STim.Szeto@Sun.COM 			break;
26969585STim.Szeto@Sun.COM 		case STMF_LU_PROP_FILENAME:
26979585STim.Szeto@Sun.COM 			if (diskLu->luDataFileNameValid == B_FALSE) {
26989585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
26999585STim.Szeto@Sun.COM 			}
27009585STim.Szeto@Sun.COM 			if ((reqLen = strlcpy(propVal, diskLu->luDataFileName,
27019585STim.Szeto@Sun.COM 			    *propLen)) >= *propLen) {
27029585STim.Szeto@Sun.COM 				*propLen = reqLen + 1;
27039585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
27049585STim.Szeto@Sun.COM 			}
27059585STim.Szeto@Sun.COM 			break;
27069585STim.Szeto@Sun.COM 		case STMF_LU_PROP_META_FILENAME:
27079585STim.Szeto@Sun.COM 			if (diskLu->luMetaFileNameValid == B_FALSE) {
27089585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
27099585STim.Szeto@Sun.COM 			}
27109585STim.Szeto@Sun.COM 			if ((reqLen = strlcpy(propVal, diskLu->luMetaFileName,
27119585STim.Szeto@Sun.COM 			    *propLen)) >= *propLen) {
27129585STim.Szeto@Sun.COM 				*propLen = reqLen + 1;
27139585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
27149585STim.Szeto@Sun.COM 			}
27159585STim.Szeto@Sun.COM 			break;
271610113SNattuvetty.Bhavyan@Sun.COM 		case STMF_LU_PROP_MGMT_URL:
271710113SNattuvetty.Bhavyan@Sun.COM 			if (diskLu->luMgmtUrlValid == B_FALSE) {
271810113SNattuvetty.Bhavyan@Sun.COM 				return (STMF_ERROR_NO_PROP);
271910113SNattuvetty.Bhavyan@Sun.COM 			}
272010113SNattuvetty.Bhavyan@Sun.COM 			if ((reqLen = strlcpy(propVal, diskLu->luMgmtUrl,
272110113SNattuvetty.Bhavyan@Sun.COM 			    *propLen)) >= *propLen) {
272210113SNattuvetty.Bhavyan@Sun.COM 				*propLen = reqLen + 1;
272310113SNattuvetty.Bhavyan@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
272410113SNattuvetty.Bhavyan@Sun.COM 			}
272510113SNattuvetty.Bhavyan@Sun.COM 			break;
27269585STim.Szeto@Sun.COM 		case STMF_LU_PROP_GUID:
27279585STim.Szeto@Sun.COM 			if (diskLu->luGuidValid == B_FALSE) {
27289585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
27299585STim.Szeto@Sun.COM 			}
27309585STim.Szeto@Sun.COM 			reqLen = snprintf(propVal, *propLen,
27319585STim.Szeto@Sun.COM 			    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X"
27329585STim.Szeto@Sun.COM 			    "%02X%02X%02X%02X",
27339585STim.Szeto@Sun.COM 			    diskLu->luGuid[0], diskLu->luGuid[1],
27349585STim.Szeto@Sun.COM 			    diskLu->luGuid[2], diskLu->luGuid[3],
27359585STim.Szeto@Sun.COM 			    diskLu->luGuid[4], diskLu->luGuid[5],
27369585STim.Szeto@Sun.COM 			    diskLu->luGuid[6], diskLu->luGuid[7],
27379585STim.Szeto@Sun.COM 			    diskLu->luGuid[8], diskLu->luGuid[9],
27389585STim.Szeto@Sun.COM 			    diskLu->luGuid[10], diskLu->luGuid[11],
27399585STim.Szeto@Sun.COM 			    diskLu->luGuid[12], diskLu->luGuid[13],
27409585STim.Szeto@Sun.COM 			    diskLu->luGuid[14], diskLu->luGuid[15]);
27419585STim.Szeto@Sun.COM 			if (reqLen >= *propLen) {
27429585STim.Szeto@Sun.COM 				*propLen = reqLen + 1;
27439585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
27449585STim.Szeto@Sun.COM 			}
27459585STim.Szeto@Sun.COM 			break;
27469585STim.Szeto@Sun.COM 		case STMF_LU_PROP_SERIAL_NUM:
27479585STim.Szeto@Sun.COM 			if (diskLu->serialNumValid == B_FALSE) {
27489585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
27499585STim.Szeto@Sun.COM 			}
27509585STim.Szeto@Sun.COM 			if ((reqLen = strlcpy(propVal, diskLu->serialNum,
27519585STim.Szeto@Sun.COM 			    *propLen)) >= *propLen) {
27529585STim.Szeto@Sun.COM 				*propLen = reqLen + 1;
27539585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
27549585STim.Szeto@Sun.COM 			}
27559585STim.Szeto@Sun.COM 			break;
27569585STim.Szeto@Sun.COM 		case STMF_LU_PROP_SIZE:
27579585STim.Szeto@Sun.COM 			if (diskLu->luSizeValid == B_FALSE) {
27589585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
27599585STim.Szeto@Sun.COM 			}
27609585STim.Szeto@Sun.COM 			(void) snprintf(propVal, *propLen, "%llu",
27619585STim.Szeto@Sun.COM 			    (u_longlong_t)diskLu->luSize);
27629585STim.Szeto@Sun.COM 			break;
27639585STim.Szeto@Sun.COM 		case STMF_LU_PROP_ALIAS:
27649585STim.Szeto@Sun.COM 			if (diskLu->luAliasValid == B_FALSE) {
27659585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
27669585STim.Szeto@Sun.COM 			}
27679585STim.Szeto@Sun.COM 			if ((reqLen = strlcpy(propVal, diskLu->luAlias,
27689585STim.Szeto@Sun.COM 			    *propLen)) >= *propLen) {
27699585STim.Szeto@Sun.COM 				*propLen = reqLen + 1;
27709585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
27719585STim.Szeto@Sun.COM 			}
27729585STim.Szeto@Sun.COM 			break;
27739585STim.Szeto@Sun.COM 		case STMF_LU_PROP_VID:
27749585STim.Szeto@Sun.COM 			if (diskLu->vidValid == B_FALSE) {
27759585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
27769585STim.Szeto@Sun.COM 			}
27779585STim.Szeto@Sun.COM 			if (*propLen <= sizeof (diskLu->vid)) {
27789585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
27799585STim.Szeto@Sun.COM 			}
27809585STim.Szeto@Sun.COM 			bcopy(diskLu->vid, propVal, sizeof (diskLu->vid));
27819585STim.Szeto@Sun.COM 			propVal[sizeof (diskLu->vid)] = 0;
27829585STim.Szeto@Sun.COM 			break;
27839585STim.Szeto@Sun.COM 		case STMF_LU_PROP_PID:
27849585STim.Szeto@Sun.COM 			if (diskLu->pidValid == B_FALSE) {
27859585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
27869585STim.Szeto@Sun.COM 			}
27879585STim.Szeto@Sun.COM 			if (*propLen <= sizeof (diskLu->pid)) {
27889585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
27899585STim.Szeto@Sun.COM 			}
27909585STim.Szeto@Sun.COM 			bcopy(diskLu->pid, propVal, sizeof (diskLu->pid));
27919585STim.Szeto@Sun.COM 			propVal[sizeof (diskLu->pid)] = 0;
27929585STim.Szeto@Sun.COM 			break;
27939585STim.Szeto@Sun.COM 		case STMF_LU_PROP_WRITE_PROTECT:
27949585STim.Szeto@Sun.COM 			if (diskLu->writeProtectEnableValid == B_FALSE) {
27959585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
27969585STim.Szeto@Sun.COM 			}
27979585STim.Szeto@Sun.COM 			if (diskLu->writeProtectEnable) {
27989585STim.Szeto@Sun.COM 				if ((reqLen = strlcpy(propVal, "true",
27999585STim.Szeto@Sun.COM 				    *propLen)) >= *propLen) {
28009585STim.Szeto@Sun.COM 					*propLen = reqLen + 1;
28019585STim.Szeto@Sun.COM 					return (STMF_ERROR_INVALID_ARG);
28029585STim.Szeto@Sun.COM 				}
28039585STim.Szeto@Sun.COM 			} else {
28049585STim.Szeto@Sun.COM 				if ((reqLen = strlcpy(propVal, "false",
28059585STim.Szeto@Sun.COM 				    *propLen)) >= *propLen) {
28069585STim.Szeto@Sun.COM 					*propLen = reqLen + 1;
28079585STim.Szeto@Sun.COM 					return (STMF_ERROR_INVALID_ARG);
28089585STim.Szeto@Sun.COM 				}
28099585STim.Szeto@Sun.COM 			}
28109585STim.Szeto@Sun.COM 			break;
28119585STim.Szeto@Sun.COM 		case STMF_LU_PROP_WRITE_CACHE_DISABLE:
28129585STim.Szeto@Sun.COM 			if (diskLu->writebackCacheDisableValid == B_FALSE) {
28139585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
28149585STim.Szeto@Sun.COM 			}
28159585STim.Szeto@Sun.COM 			if (diskLu->writebackCacheDisable) {
28169585STim.Szeto@Sun.COM 				if ((reqLen = strlcpy(propVal, "true",
28179585STim.Szeto@Sun.COM 				    *propLen)) >= *propLen) {
28189585STim.Szeto@Sun.COM 					*propLen = reqLen + 1;
28199585STim.Szeto@Sun.COM 					return (STMF_ERROR_INVALID_ARG);
28209585STim.Szeto@Sun.COM 				}
28219585STim.Szeto@Sun.COM 			} else {
28229585STim.Szeto@Sun.COM 				if ((reqLen = strlcpy(propVal, "false",
28239585STim.Szeto@Sun.COM 				    *propLen)) >= *propLen) {
28249585STim.Szeto@Sun.COM 					*propLen = reqLen + 1;
28259585STim.Szeto@Sun.COM 					return (STMF_ERROR_INVALID_ARG);
28269585STim.Szeto@Sun.COM 				}
28279585STim.Szeto@Sun.COM 			}
28289585STim.Szeto@Sun.COM 			break;
28299585STim.Szeto@Sun.COM 		default:
2830*11691SSrivijitha.Dugganapalli@Sun.COM 			ret = STMF_ERROR_INVALID_PROP;
28319585STim.Szeto@Sun.COM 			break;
28329585STim.Szeto@Sun.COM 	}
28339585STim.Szeto@Sun.COM 
28349585STim.Szeto@Sun.COM 	return (ret);
28359585STim.Szeto@Sun.COM }
28369585STim.Szeto@Sun.COM 
28379585STim.Szeto@Sun.COM /*
28389585STim.Szeto@Sun.COM  * setDiskProp
28399585STim.Szeto@Sun.COM  *
28409585STim.Szeto@Sun.COM  * Purpose: set properties for resource of type disk
28419585STim.Szeto@Sun.COM  *
28429585STim.Szeto@Sun.COM  * hdl - allocated luResourceImpl
28439585STim.Szeto@Sun.COM  * resourceProp - valid resource identifier
28449585STim.Szeto@Sun.COM  * propVal - valid resource value
28459585STim.Szeto@Sun.COM  */
28469585STim.Szeto@Sun.COM static int
28479585STim.Szeto@Sun.COM setDiskProp(luResourceImpl *hdl, uint32_t resourceProp, const char *propVal)
28489585STim.Szeto@Sun.COM {
28499585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
28509585STim.Szeto@Sun.COM 	int i;
28519585STim.Szeto@Sun.COM 	diskResource *diskLu = hdl->resource;
28529585STim.Szeto@Sun.COM 	unsigned long long numericProp = 0;
28539585STim.Szeto@Sun.COM 	char guidProp[LU_ASCII_GUID_SIZE + 1];
28549585STim.Szeto@Sun.COM 	char ouiProp[OUI_ASCII_SIZE + 1];
285510765SJohn.Forte@Sun.COM 	char hostIdProp[HOST_ID_ASCII_SIZE + 1];
28569585STim.Szeto@Sun.COM 	unsigned int oui[OUI_SIZE];
285710765SJohn.Forte@Sun.COM 	unsigned int hostId[HOST_ID_SIZE];
28589585STim.Szeto@Sun.COM 	unsigned int guid[LU_GUID_SIZE];
28599585STim.Szeto@Sun.COM 	int propSize;
28609585STim.Szeto@Sun.COM 
28619585STim.Szeto@Sun.COM 
28629585STim.Szeto@Sun.COM 	if (propVal == NULL) {
28639585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
28649585STim.Szeto@Sun.COM 	}
28659585STim.Szeto@Sun.COM 
28669585STim.Szeto@Sun.COM 	switch (resourceProp) {
28679585STim.Szeto@Sun.COM 		case STMF_LU_PROP_ALIAS:
28689585STim.Szeto@Sun.COM 			if (strlcpy(diskLu->luAlias, propVal,
28699585STim.Szeto@Sun.COM 			    sizeof (diskLu->luAlias)) >=
28709585STim.Szeto@Sun.COM 			    sizeof (diskLu->luAlias)) {
28719585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
28729585STim.Szeto@Sun.COM 			}
28739585STim.Szeto@Sun.COM 			diskLu->luAliasValid = B_TRUE;
28749585STim.Szeto@Sun.COM 			break;
28759585STim.Szeto@Sun.COM 		case STMF_LU_PROP_BLOCK_SIZE:
28769585STim.Szeto@Sun.COM 			(void) sscanf(propVal, "%llu", &numericProp);
28779585STim.Szeto@Sun.COM 			if (numericProp > UINT16_MAX) {
28789585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
28799585STim.Szeto@Sun.COM 			}
28809585STim.Szeto@Sun.COM 			diskLu->blkSize = numericProp;
28819585STim.Szeto@Sun.COM 			diskLu->blkSizeValid = B_TRUE;
28829585STim.Szeto@Sun.COM 			break;
28839585STim.Szeto@Sun.COM 		case STMF_LU_PROP_COMPANY_ID:
28849585STim.Szeto@Sun.COM 			if ((strlcpy(ouiProp, propVal, sizeof (ouiProp))) >=
28859585STim.Szeto@Sun.COM 			    sizeof (ouiProp)) {
28869585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
28879585STim.Szeto@Sun.COM 			}
28889585STim.Szeto@Sun.COM 			if (checkHexUpper(ouiProp) != 0) {
28899585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
28909585STim.Szeto@Sun.COM 			}
28919585STim.Szeto@Sun.COM 			(void) sscanf(ouiProp, "%2X%2X%2X",
28929585STim.Szeto@Sun.COM 			    &oui[0], &oui[1], &oui[2]);
28939585STim.Szeto@Sun.COM 
28949585STim.Szeto@Sun.COM 			diskLu->companyId = 0;
28959585STim.Szeto@Sun.COM 			diskLu->companyId += oui[0] << 16;
28969585STim.Szeto@Sun.COM 			diskLu->companyId += oui[1] << 8;
28979585STim.Szeto@Sun.COM 			diskLu->companyId += oui[2];
289810765SJohn.Forte@Sun.COM 			if (diskLu->companyId == 0) {
289910765SJohn.Forte@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
290010765SJohn.Forte@Sun.COM 			}
29019585STim.Szeto@Sun.COM 			diskLu->companyIdValid = B_TRUE;
29029585STim.Szeto@Sun.COM 			break;
290310765SJohn.Forte@Sun.COM 		case STMF_LU_PROP_HOST_ID:
290410765SJohn.Forte@Sun.COM 			if ((strlcpy(hostIdProp, propVal,
290510765SJohn.Forte@Sun.COM 			    sizeof (hostIdProp))) >= sizeof (hostIdProp)) {
290610765SJohn.Forte@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
290710765SJohn.Forte@Sun.COM 			}
290810765SJohn.Forte@Sun.COM 			if (checkHexUpper(hostIdProp) != 0) {
290910765SJohn.Forte@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
291010765SJohn.Forte@Sun.COM 			}
291110765SJohn.Forte@Sun.COM 			(void) sscanf(hostIdProp, "%2X%2X%2X%2X",
291210765SJohn.Forte@Sun.COM 			    &hostId[0], &hostId[1], &hostId[2], &hostId[3]);
291310765SJohn.Forte@Sun.COM 
291410765SJohn.Forte@Sun.COM 			diskLu->hostId = 0;
291510765SJohn.Forte@Sun.COM 			diskLu->hostId += hostId[0] << 24;
291610765SJohn.Forte@Sun.COM 			diskLu->hostId += hostId[1] << 16;
291710765SJohn.Forte@Sun.COM 			diskLu->hostId += hostId[2] << 8;
291810765SJohn.Forte@Sun.COM 			diskLu->hostId += hostId[3];
291910765SJohn.Forte@Sun.COM 			if (diskLu->hostId == 0) {
292010765SJohn.Forte@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
292110765SJohn.Forte@Sun.COM 			}
292210765SJohn.Forte@Sun.COM 			diskLu->hostIdValid = B_TRUE;
292310765SJohn.Forte@Sun.COM 			break;
29249585STim.Szeto@Sun.COM 		case STMF_LU_PROP_GUID:
29259585STim.Szeto@Sun.COM 			if (strlen(propVal) != LU_ASCII_GUID_SIZE) {
29269585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
29279585STim.Szeto@Sun.COM 			}
29289585STim.Szeto@Sun.COM 
29299585STim.Szeto@Sun.COM 			if ((strlcpy(guidProp, propVal, sizeof (guidProp))) >=
29309585STim.Szeto@Sun.COM 			    sizeof (guidProp)) {
29319585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
29329585STim.Szeto@Sun.COM 			}
29339585STim.Szeto@Sun.COM 
29349585STim.Szeto@Sun.COM 			if (checkHexUpper(guidProp) != 0) {
29359585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
29369585STim.Szeto@Sun.COM 			}
29379585STim.Szeto@Sun.COM 
29389585STim.Szeto@Sun.COM 			(void) sscanf(guidProp,
29399585STim.Szeto@Sun.COM 			    "%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X",
29409585STim.Szeto@Sun.COM 			    &guid[0], &guid[1], &guid[2], &guid[3], &guid[4],
29419585STim.Szeto@Sun.COM 			    &guid[5], &guid[6], &guid[7], &guid[8], &guid[9],
29429585STim.Szeto@Sun.COM 			    &guid[10], &guid[11], &guid[12], &guid[13],
29439585STim.Szeto@Sun.COM 			    &guid[14], &guid[15]);
29449585STim.Szeto@Sun.COM 			for (i = 0; i < sizeof (diskLu->luGuid); i++) {
29459585STim.Szeto@Sun.COM 				diskLu->luGuid[i] = guid[i];
29469585STim.Szeto@Sun.COM 			}
29479585STim.Szeto@Sun.COM 			diskLu->luGuidValid = B_TRUE;
29489585STim.Szeto@Sun.COM 			break;
29499585STim.Szeto@Sun.COM 		case STMF_LU_PROP_FILENAME:
29509585STim.Szeto@Sun.COM 			if ((strlcpy(diskLu->luDataFileName, propVal,
29519585STim.Szeto@Sun.COM 			    sizeof (diskLu->luDataFileName))) >=
29529585STim.Szeto@Sun.COM 			    sizeof (diskLu->luDataFileName)) {
29539585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
29549585STim.Szeto@Sun.COM 			}
29559585STim.Szeto@Sun.COM 			diskLu->luDataFileNameValid = B_TRUE;
29569585STim.Szeto@Sun.COM 			break;
29579585STim.Szeto@Sun.COM 		case STMF_LU_PROP_META_FILENAME:
29589585STim.Szeto@Sun.COM 			if ((strlcpy(diskLu->luMetaFileName, propVal,
29599585STim.Szeto@Sun.COM 			    sizeof (diskLu->luMetaFileName))) >=
29609585STim.Szeto@Sun.COM 			    sizeof (diskLu->luMetaFileName)) {
29619585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
29629585STim.Szeto@Sun.COM 			}
29639585STim.Szeto@Sun.COM 			diskLu->luMetaFileNameValid = B_TRUE;
29649585STim.Szeto@Sun.COM 			break;
296510113SNattuvetty.Bhavyan@Sun.COM 		case STMF_LU_PROP_MGMT_URL:
296610113SNattuvetty.Bhavyan@Sun.COM 			if ((strlcpy(diskLu->luMgmtUrl, propVal,
296710113SNattuvetty.Bhavyan@Sun.COM 			    sizeof (diskLu->luMgmtUrl))) >=
296810113SNattuvetty.Bhavyan@Sun.COM 			    sizeof (diskLu->luMgmtUrl)) {
296910113SNattuvetty.Bhavyan@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
297010113SNattuvetty.Bhavyan@Sun.COM 			}
297110113SNattuvetty.Bhavyan@Sun.COM 			diskLu->luMgmtUrlValid = B_TRUE;
297210113SNattuvetty.Bhavyan@Sun.COM 			break;
29739585STim.Szeto@Sun.COM 		case STMF_LU_PROP_PID:
29749585STim.Szeto@Sun.COM 			if ((propSize = strlen(propVal)) >
29759585STim.Szeto@Sun.COM 			    sizeof (diskLu->pid)) {
29769585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
29779585STim.Szeto@Sun.COM 			}
29789585STim.Szeto@Sun.COM 			(void) strncpy(diskLu->pid, propVal, propSize);
29799585STim.Szeto@Sun.COM 			diskLu->pidValid = B_TRUE;
29809585STim.Szeto@Sun.COM 			break;
29819585STim.Szeto@Sun.COM 		case STMF_LU_PROP_SERIAL_NUM:
29829585STim.Szeto@Sun.COM 			if ((propSize = strlen(propVal)) >
29839585STim.Szeto@Sun.COM 			    (sizeof (diskLu->serialNum) - 1)) {
29849585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
29859585STim.Szeto@Sun.COM 			}
29869585STim.Szeto@Sun.COM 			(void) strncpy(diskLu->serialNum, propVal, propSize);
29879585STim.Szeto@Sun.COM 			diskLu->serialNumValid = B_TRUE;
29889585STim.Szeto@Sun.COM 			break;
29899585STim.Szeto@Sun.COM 		case STMF_LU_PROP_SIZE:
29909585STim.Szeto@Sun.COM 			if ((niceStrToNum(propVal, &diskLu->luSize) != 0)) {
29919585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
29929585STim.Szeto@Sun.COM 			}
29939585STim.Szeto@Sun.COM 			diskLu->luSizeValid = B_TRUE;
29949585STim.Szeto@Sun.COM 			break;
29959585STim.Szeto@Sun.COM 		case STMF_LU_PROP_VID:
29969585STim.Szeto@Sun.COM 			if ((propSize = strlen(propVal)) >
29979585STim.Szeto@Sun.COM 			    sizeof (diskLu->vid)) {
29989585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
29999585STim.Szeto@Sun.COM 			}
30009585STim.Szeto@Sun.COM 			(void) strncpy(diskLu->vid, propVal, propSize);
30019585STim.Szeto@Sun.COM 			diskLu->vidValid = B_TRUE;
30029585STim.Szeto@Sun.COM 			break;
30039585STim.Szeto@Sun.COM 		case STMF_LU_PROP_WRITE_PROTECT:
30049585STim.Szeto@Sun.COM 			if (strcasecmp(propVal, "TRUE") == 0) {
30059585STim.Szeto@Sun.COM 				diskLu->writeProtectEnable = B_TRUE;
30069585STim.Szeto@Sun.COM 			} else if (strcasecmp(propVal, "FALSE") == 0) {
30079585STim.Szeto@Sun.COM 				diskLu->writeProtectEnable = B_FALSE;
30089585STim.Szeto@Sun.COM 			} else {
30099585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
30109585STim.Szeto@Sun.COM 			}
30119585STim.Szeto@Sun.COM 			diskLu->writeProtectEnableValid = B_TRUE;
30129585STim.Szeto@Sun.COM 			break;
30139585STim.Szeto@Sun.COM 		case STMF_LU_PROP_WRITE_CACHE_DISABLE:
30149585STim.Szeto@Sun.COM 			if (strcasecmp(propVal, "TRUE") == 0) {
30159585STim.Szeto@Sun.COM 				diskLu->writebackCacheDisable = B_TRUE;
30169585STim.Szeto@Sun.COM 			} else if (strcasecmp(propVal, "FALSE") == 0) {
30179585STim.Szeto@Sun.COM 				diskLu->writebackCacheDisable = B_FALSE;
30189585STim.Szeto@Sun.COM 			} else {
30199585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
30209585STim.Szeto@Sun.COM 			}
30219585STim.Szeto@Sun.COM 			diskLu->writebackCacheDisableValid = B_TRUE;
30229585STim.Szeto@Sun.COM 			break;
302310725SJohn.Forte@Sun.COM 		case STMF_LU_PROP_ACCESS_STATE:
302410725SJohn.Forte@Sun.COM 			ret = STMF_ERROR_INVALID_PROP;
302510725SJohn.Forte@Sun.COM 			break;
30269585STim.Szeto@Sun.COM 		default:
3027*11691SSrivijitha.Dugganapalli@Sun.COM 			ret = STMF_ERROR_INVALID_PROP;
30289585STim.Szeto@Sun.COM 			break;
30299585STim.Szeto@Sun.COM 	}
30309585STim.Szeto@Sun.COM 	return (ret);
30319585STim.Szeto@Sun.COM }
30329585STim.Szeto@Sun.COM 
30339585STim.Szeto@Sun.COM static int
30349585STim.Szeto@Sun.COM checkHexUpper(char *buf)
30359585STim.Szeto@Sun.COM {
30369585STim.Szeto@Sun.COM 	int i;
30379585STim.Szeto@Sun.COM 
30389585STim.Szeto@Sun.COM 	for (i = 0; i < strlen(buf); i++) {
30399585STim.Szeto@Sun.COM 		if (isxdigit(buf[i])) {
30409585STim.Szeto@Sun.COM 			buf[i] = toupper(buf[i]);
30419585STim.Szeto@Sun.COM 			continue;
30429585STim.Szeto@Sun.COM 		}
30439585STim.Szeto@Sun.COM 		return (-1);
30449585STim.Szeto@Sun.COM 	}
30459585STim.Szeto@Sun.COM 
30469585STim.Szeto@Sun.COM 	return (0);
30479585STim.Szeto@Sun.COM }
30489585STim.Szeto@Sun.COM 
30499585STim.Szeto@Sun.COM /*
30509585STim.Szeto@Sun.COM  * Given a numeric suffix, convert the value into a number of bits that the
30519585STim.Szeto@Sun.COM  * resulting value must be shifted.
30529585STim.Szeto@Sun.COM  * Code lifted from libzfs_util.c
30539585STim.Szeto@Sun.COM  */
30549585STim.Szeto@Sun.COM static int
30559585STim.Szeto@Sun.COM strToShift(const char *buf)
30569585STim.Szeto@Sun.COM {
30579585STim.Szeto@Sun.COM 	const char *ends = "BKMGTPE";
30589585STim.Szeto@Sun.COM 	int i;
30599585STim.Szeto@Sun.COM 
30609585STim.Szeto@Sun.COM 	if (buf[0] == '\0')
30619585STim.Szeto@Sun.COM 		return (0);
30629585STim.Szeto@Sun.COM 
30639585STim.Szeto@Sun.COM 	for (i = 0; i < strlen(ends); i++) {
30649585STim.Szeto@Sun.COM 		if (toupper(buf[0]) == ends[i])
30659585STim.Szeto@Sun.COM 			return (10*i);
30669585STim.Szeto@Sun.COM 	}
30679585STim.Szeto@Sun.COM 
30689585STim.Szeto@Sun.COM 	return (-1);
30699585STim.Szeto@Sun.COM }
30709585STim.Szeto@Sun.COM 
30719585STim.Szeto@Sun.COM int
30729585STim.Szeto@Sun.COM stmfFreeLuResource(luResource hdl)
30739585STim.Szeto@Sun.COM {
30749585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
30759585STim.Szeto@Sun.COM 	if (hdl == NULL) {
30769585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
30779585STim.Szeto@Sun.COM 	}
30789585STim.Szeto@Sun.COM 
30799585STim.Szeto@Sun.COM 	luResourceImpl *hdlImpl = hdl;
30809585STim.Szeto@Sun.COM 	free(hdlImpl->resource);
30819585STim.Szeto@Sun.COM 	free(hdlImpl);
30829585STim.Szeto@Sun.COM 	return (ret);
30839585STim.Szeto@Sun.COM }
30849585STim.Szeto@Sun.COM 
30859585STim.Szeto@Sun.COM /*
30869585STim.Szeto@Sun.COM  * Convert a string of the form '100G' into a real number. Used when setting
30879585STim.Szeto@Sun.COM  * the size of a logical unit.
30889585STim.Szeto@Sun.COM  * Code lifted from libzfs_util.c
30899585STim.Szeto@Sun.COM  */
30909585STim.Szeto@Sun.COM static int
30919585STim.Szeto@Sun.COM niceStrToNum(const char *value, uint64_t *num)
30929585STim.Szeto@Sun.COM {
30939585STim.Szeto@Sun.COM 	char *end;
30949585STim.Szeto@Sun.COM 	int shift;
30959585STim.Szeto@Sun.COM 
30969585STim.Szeto@Sun.COM 	*num = 0;
30979585STim.Szeto@Sun.COM 
30989585STim.Szeto@Sun.COM 	/* Check to see if this looks like a number.  */
30999585STim.Szeto@Sun.COM 	if ((value[0] < '0' || value[0] > '9') && value[0] != '.') {
31009585STim.Szeto@Sun.COM 		return (-1);
31019585STim.Szeto@Sun.COM 	}
31029585STim.Szeto@Sun.COM 
31039585STim.Szeto@Sun.COM 	/* Rely on stroull() to process the numeric portion.  */
31049585STim.Szeto@Sun.COM 	errno = 0;
31059585STim.Szeto@Sun.COM 	*num = strtoull(value, &end, 10);
31069585STim.Szeto@Sun.COM 
31079585STim.Szeto@Sun.COM 	/*
31089585STim.Szeto@Sun.COM 	 * Check for ERANGE, which indicates that the value is too large to fit
31099585STim.Szeto@Sun.COM 	 * in a 64-bit value.
31109585STim.Szeto@Sun.COM 	 */
31119585STim.Szeto@Sun.COM 	if (errno == ERANGE) {
31129585STim.Szeto@Sun.COM 		return (-1);
31139585STim.Szeto@Sun.COM 	}
31149585STim.Szeto@Sun.COM 
31159585STim.Szeto@Sun.COM 	/*
31169585STim.Szeto@Sun.COM 	 * If we have a decimal value, then do the computation with floating
31179585STim.Szeto@Sun.COM 	 * point arithmetic.  Otherwise, use standard arithmetic.
31189585STim.Szeto@Sun.COM 	 */
31199585STim.Szeto@Sun.COM 	if (*end == '.') {
31209585STim.Szeto@Sun.COM 		double fval = strtod(value, &end);
31219585STim.Szeto@Sun.COM 
31229585STim.Szeto@Sun.COM 		if ((shift = strToShift(end)) == -1) {
31239585STim.Szeto@Sun.COM 			return (-1);
31249585STim.Szeto@Sun.COM 		}
31259585STim.Szeto@Sun.COM 
31269585STim.Szeto@Sun.COM 		fval *= pow(2, shift);
31279585STim.Szeto@Sun.COM 
31289585STim.Szeto@Sun.COM 		if (fval > UINT64_MAX) {
31299585STim.Szeto@Sun.COM 			return (-1);
31309585STim.Szeto@Sun.COM 		}
31319585STim.Szeto@Sun.COM 
31329585STim.Szeto@Sun.COM 		*num = (uint64_t)fval;
31339585STim.Szeto@Sun.COM 	} else {
31349585STim.Szeto@Sun.COM 		if ((shift = strToShift(end)) == -1) {
31359585STim.Szeto@Sun.COM 			return (-1);
31369585STim.Szeto@Sun.COM 		}
31379585STim.Szeto@Sun.COM 
31389585STim.Szeto@Sun.COM 		/* Check for overflow */
31399585STim.Szeto@Sun.COM 		if (shift >= 64 || (*num << shift) >> shift != *num) {
31409585STim.Szeto@Sun.COM 			return (-1);
31419585STim.Szeto@Sun.COM 		}
31429585STim.Szeto@Sun.COM 
31439585STim.Szeto@Sun.COM 		*num <<= shift;
31449585STim.Szeto@Sun.COM 	}
31459585STim.Szeto@Sun.COM 
31469585STim.Szeto@Sun.COM 	return (0);
31479585STim.Szeto@Sun.COM }
31489585STim.Szeto@Sun.COM 
31499585STim.Szeto@Sun.COM /*
31507836SJohn.Forte@Sun.COM  * stmfCreateTargetGroup
31517836SJohn.Forte@Sun.COM  *
31527836SJohn.Forte@Sun.COM  * Purpose: Create a local port group
31537836SJohn.Forte@Sun.COM  *
31547836SJohn.Forte@Sun.COM  * targetGroupName - name of local port group to create
31557836SJohn.Forte@Sun.COM  */
31567836SJohn.Forte@Sun.COM int
31577836SJohn.Forte@Sun.COM stmfCreateTargetGroup(stmfGroupName *targetGroupName)
31587836SJohn.Forte@Sun.COM {
31597836SJohn.Forte@Sun.COM 	int ret;
31607836SJohn.Forte@Sun.COM 	int fd;
31617836SJohn.Forte@Sun.COM 
31627836SJohn.Forte@Sun.COM 	if (targetGroupName == NULL ||
31637836SJohn.Forte@Sun.COM 	    (strnlen((char *)targetGroupName, sizeof (stmfGroupName))
31647836SJohn.Forte@Sun.COM 	    == sizeof (stmfGroupName))) {
31657836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
31667836SJohn.Forte@Sun.COM 	}
31677836SJohn.Forte@Sun.COM 
31687836SJohn.Forte@Sun.COM 	/* Check to ensure service exists */
31697836SJohn.Forte@Sun.COM 	if (psCheckService() != STMF_STATUS_SUCCESS) {
31707836SJohn.Forte@Sun.COM 		return (STMF_ERROR_SERVICE_NOT_FOUND);
31717836SJohn.Forte@Sun.COM 	}
31727836SJohn.Forte@Sun.COM 
31737836SJohn.Forte@Sun.COM 	/* call init */
31747836SJohn.Forte@Sun.COM 	ret = initializeConfig();
31757836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
31767836SJohn.Forte@Sun.COM 		return (ret);
31777836SJohn.Forte@Sun.COM 	}
31787836SJohn.Forte@Sun.COM 
31797836SJohn.Forte@Sun.COM 	/*
31807836SJohn.Forte@Sun.COM 	 * Open control node for stmf
31817836SJohn.Forte@Sun.COM 	 */
31827836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
31837836SJohn.Forte@Sun.COM 		return (ret);
31847836SJohn.Forte@Sun.COM 
31857836SJohn.Forte@Sun.COM 	/*
31867836SJohn.Forte@Sun.COM 	 * Add the group to the driver
31877836SJohn.Forte@Sun.COM 	 */
31887836SJohn.Forte@Sun.COM 	if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_TARGET_GROUP,
31897836SJohn.Forte@Sun.COM 	    targetGroupName)) != STMF_STATUS_SUCCESS) {
31907836SJohn.Forte@Sun.COM 		goto done;
31917836SJohn.Forte@Sun.COM 	}
31927836SJohn.Forte@Sun.COM 
31939585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
31949585STim.Szeto@Sun.COM 		goto done;
31959585STim.Szeto@Sun.COM 	}
31969585STim.Szeto@Sun.COM 
31977836SJohn.Forte@Sun.COM 	/*
31987836SJohn.Forte@Sun.COM 	 * If the add to the driver was successful, add it to the persistent
31997836SJohn.Forte@Sun.COM 	 * store.
32007836SJohn.Forte@Sun.COM 	 */
32017836SJohn.Forte@Sun.COM 	ret = psCreateTargetGroup((char *)targetGroupName);
32027836SJohn.Forte@Sun.COM 	switch (ret) {
32037836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
32047836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
32057836SJohn.Forte@Sun.COM 			break;
32067836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_EXISTS:
32077836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_EXISTS;
32087836SJohn.Forte@Sun.COM 			break;
32097836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
32107836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
32117836SJohn.Forte@Sun.COM 			break;
32127836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
32137836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
32147836SJohn.Forte@Sun.COM 			break;
32157836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
32167836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
32177836SJohn.Forte@Sun.COM 			break;
32187836SJohn.Forte@Sun.COM 		default:
32197836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
32207836SJohn.Forte@Sun.COM 			    "stmfCreateTargetGroup:psCreateTargetGroup"
32217836SJohn.Forte@Sun.COM 			    ":error(%d)", ret);
32227836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
32237836SJohn.Forte@Sun.COM 			break;
32247836SJohn.Forte@Sun.COM 	}
32257836SJohn.Forte@Sun.COM 
32267836SJohn.Forte@Sun.COM done:
32277836SJohn.Forte@Sun.COM 	(void) close(fd);
32287836SJohn.Forte@Sun.COM 	return (ret);
32297836SJohn.Forte@Sun.COM }
32307836SJohn.Forte@Sun.COM 
32317836SJohn.Forte@Sun.COM /*
32327836SJohn.Forte@Sun.COM  * stmfDeleteHostGroup
32337836SJohn.Forte@Sun.COM  *
32347836SJohn.Forte@Sun.COM  * Purpose: Delete an initiator or local port group
32357836SJohn.Forte@Sun.COM  *
32367836SJohn.Forte@Sun.COM  * hostGroupName - group to delete
32377836SJohn.Forte@Sun.COM  */
32387836SJohn.Forte@Sun.COM int
32397836SJohn.Forte@Sun.COM stmfDeleteHostGroup(stmfGroupName *hostGroupName)
32407836SJohn.Forte@Sun.COM {
32417836SJohn.Forte@Sun.COM 	int ret;
32427836SJohn.Forte@Sun.COM 	int fd;
32437836SJohn.Forte@Sun.COM 
32447836SJohn.Forte@Sun.COM 	if (hostGroupName == NULL) {
32457836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
32467836SJohn.Forte@Sun.COM 	}
32477836SJohn.Forte@Sun.COM 
32487836SJohn.Forte@Sun.COM 	/* Check to ensure service exists */
32497836SJohn.Forte@Sun.COM 	if (psCheckService() != STMF_STATUS_SUCCESS) {
32507836SJohn.Forte@Sun.COM 		return (STMF_ERROR_SERVICE_NOT_FOUND);
32517836SJohn.Forte@Sun.COM 	}
32527836SJohn.Forte@Sun.COM 
32537836SJohn.Forte@Sun.COM 	/* call init */
32547836SJohn.Forte@Sun.COM 	ret = initializeConfig();
32557836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
32567836SJohn.Forte@Sun.COM 		return (ret);
32577836SJohn.Forte@Sun.COM 	}
32587836SJohn.Forte@Sun.COM 
32597836SJohn.Forte@Sun.COM 	/*
32607836SJohn.Forte@Sun.COM 	 * Open control node for stmf
32617836SJohn.Forte@Sun.COM 	 */
32627836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
32637836SJohn.Forte@Sun.COM 		return (ret);
32647836SJohn.Forte@Sun.COM 
32657836SJohn.Forte@Sun.COM 	/*
32667836SJohn.Forte@Sun.COM 	 * Remove the group from the driver
32677836SJohn.Forte@Sun.COM 	 */
32687836SJohn.Forte@Sun.COM 	if ((ret = groupIoctl(fd, STMF_IOCTL_REMOVE_HOST_GROUP,
32697836SJohn.Forte@Sun.COM 	    hostGroupName)) != STMF_STATUS_SUCCESS) {
32707836SJohn.Forte@Sun.COM 		goto done;
32717836SJohn.Forte@Sun.COM 	}
32727836SJohn.Forte@Sun.COM 
32739585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
32749585STim.Szeto@Sun.COM 		goto done;
32759585STim.Szeto@Sun.COM 	}
32769585STim.Szeto@Sun.COM 
32777836SJohn.Forte@Sun.COM 	/*
32787836SJohn.Forte@Sun.COM 	 * If the remove from the driver was successful, remove it from the
32797836SJohn.Forte@Sun.COM 	 * persistent store.
32807836SJohn.Forte@Sun.COM 	 */
32817836SJohn.Forte@Sun.COM 	ret = psDeleteHostGroup((char *)hostGroupName);
32827836SJohn.Forte@Sun.COM 	switch (ret) {
32837836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
32847836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
32857836SJohn.Forte@Sun.COM 			break;
32867836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
32877836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
32887836SJohn.Forte@Sun.COM 			break;
32897836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
32907836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
32917836SJohn.Forte@Sun.COM 			break;
32927836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
32937836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
32947836SJohn.Forte@Sun.COM 			break;
32957836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
32967836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
32977836SJohn.Forte@Sun.COM 			break;
32987836SJohn.Forte@Sun.COM 		default:
32997836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
33007836SJohn.Forte@Sun.COM 			    "stmfDeleteHostGroup:psDeleteHostGroup:error(%d)",
33017836SJohn.Forte@Sun.COM 			    ret);
33027836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
33037836SJohn.Forte@Sun.COM 			break;
33047836SJohn.Forte@Sun.COM 	}
33057836SJohn.Forte@Sun.COM 
33067836SJohn.Forte@Sun.COM done:
33077836SJohn.Forte@Sun.COM 	(void) close(fd);
33087836SJohn.Forte@Sun.COM 	return (ret);
33097836SJohn.Forte@Sun.COM }
33107836SJohn.Forte@Sun.COM 
33117836SJohn.Forte@Sun.COM /*
33127836SJohn.Forte@Sun.COM  * stmfDeleteTargetGroup
33137836SJohn.Forte@Sun.COM  *
33147836SJohn.Forte@Sun.COM  * Purpose: Delete an initiator or local port group
33157836SJohn.Forte@Sun.COM  *
33167836SJohn.Forte@Sun.COM  * targetGroupName - group to delete
33177836SJohn.Forte@Sun.COM  */
33187836SJohn.Forte@Sun.COM int
33197836SJohn.Forte@Sun.COM stmfDeleteTargetGroup(stmfGroupName *targetGroupName)
33207836SJohn.Forte@Sun.COM {
33217836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
33227836SJohn.Forte@Sun.COM 	int fd;
33237836SJohn.Forte@Sun.COM 
33247836SJohn.Forte@Sun.COM 	if (targetGroupName == NULL) {
33257836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
33267836SJohn.Forte@Sun.COM 	}
33277836SJohn.Forte@Sun.COM 
33287836SJohn.Forte@Sun.COM 	/* Check to ensure service exists */
33297836SJohn.Forte@Sun.COM 	if (psCheckService() != STMF_STATUS_SUCCESS) {
33307836SJohn.Forte@Sun.COM 		return (STMF_ERROR_SERVICE_NOT_FOUND);
33317836SJohn.Forte@Sun.COM 	}
33327836SJohn.Forte@Sun.COM 
33337836SJohn.Forte@Sun.COM 	/* call init */
33347836SJohn.Forte@Sun.COM 	ret = initializeConfig();
33357836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
33367836SJohn.Forte@Sun.COM 		return (ret);
33377836SJohn.Forte@Sun.COM 	}
33387836SJohn.Forte@Sun.COM 
33397836SJohn.Forte@Sun.COM 	/*
33407836SJohn.Forte@Sun.COM 	 * Open control node for stmf
33417836SJohn.Forte@Sun.COM 	 */
33427836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
33437836SJohn.Forte@Sun.COM 		return (ret);
33447836SJohn.Forte@Sun.COM 
33457836SJohn.Forte@Sun.COM 	/*
33467836SJohn.Forte@Sun.COM 	 * Remove the group from the driver
33477836SJohn.Forte@Sun.COM 	 */
33487836SJohn.Forte@Sun.COM 	if ((ret = groupIoctl(fd, STMF_IOCTL_REMOVE_TARGET_GROUP,
33497836SJohn.Forte@Sun.COM 	    targetGroupName)) != STMF_STATUS_SUCCESS) {
33507836SJohn.Forte@Sun.COM 		goto done;
33517836SJohn.Forte@Sun.COM 	}
33527836SJohn.Forte@Sun.COM 
33539585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
33549585STim.Szeto@Sun.COM 		goto done;
33559585STim.Szeto@Sun.COM 	}
33569585STim.Szeto@Sun.COM 
33577836SJohn.Forte@Sun.COM 	/*
33587836SJohn.Forte@Sun.COM 	 * If the remove from the driver was successful, remove it from the
33597836SJohn.Forte@Sun.COM 	 * persistent store.
33607836SJohn.Forte@Sun.COM 	 */
33617836SJohn.Forte@Sun.COM 	ret = psDeleteTargetGroup((char *)targetGroupName);
33627836SJohn.Forte@Sun.COM 	switch (ret) {
33637836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
33647836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
33657836SJohn.Forte@Sun.COM 			break;
33667836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
33677836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
33687836SJohn.Forte@Sun.COM 			break;
33697836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
33707836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
33717836SJohn.Forte@Sun.COM 			break;
33727836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
33737836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
33747836SJohn.Forte@Sun.COM 			break;
33757836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
33767836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
33777836SJohn.Forte@Sun.COM 			break;
33787836SJohn.Forte@Sun.COM 		default:
33797836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
33807836SJohn.Forte@Sun.COM 			    "stmfDeleteTargetGroup:psDeleteTargetGroup"
33817836SJohn.Forte@Sun.COM 			    ":error(%d)", ret);
33827836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
33837836SJohn.Forte@Sun.COM 			break;
33847836SJohn.Forte@Sun.COM 	}
33857836SJohn.Forte@Sun.COM 
33867836SJohn.Forte@Sun.COM done:
33877836SJohn.Forte@Sun.COM 	(void) close(fd);
33887836SJohn.Forte@Sun.COM 	return (ret);
33897836SJohn.Forte@Sun.COM }
33907836SJohn.Forte@Sun.COM 
33917836SJohn.Forte@Sun.COM /*
33927836SJohn.Forte@Sun.COM  * stmfDevidFromIscsiName
33937836SJohn.Forte@Sun.COM  *
33947836SJohn.Forte@Sun.COM  * Purpose: convert an iSCSI name to an stmf devid
33957836SJohn.Forte@Sun.COM  *
33967836SJohn.Forte@Sun.COM  * iscsiName - unicode nul terminated utf-8 encoded iSCSI name
33977836SJohn.Forte@Sun.COM  * devid - on success, contains the converted iscsi name
33987836SJohn.Forte@Sun.COM  */
33997836SJohn.Forte@Sun.COM int
34007836SJohn.Forte@Sun.COM stmfDevidFromIscsiName(char *iscsiName, stmfDevid *devid)
34017836SJohn.Forte@Sun.COM {
34027836SJohn.Forte@Sun.COM 	if (devid == NULL || iscsiName == NULL)
34037836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
34047836SJohn.Forte@Sun.COM 
34057836SJohn.Forte@Sun.COM 	bzero(devid, sizeof (stmfDevid));
34067836SJohn.Forte@Sun.COM 
34077836SJohn.Forte@Sun.COM 	/* Validate size of target */
34087836SJohn.Forte@Sun.COM 	if ((devid->identLength = strlen(iscsiName)) > MAX_ISCSI_NAME ||
34097836SJohn.Forte@Sun.COM 	    devid->identLength < strlen(EUI) ||
34107836SJohn.Forte@Sun.COM 	    devid->identLength < strlen(IQN)) {
34117836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
34127836SJohn.Forte@Sun.COM 	}
34137836SJohn.Forte@Sun.COM 
34147836SJohn.Forte@Sun.COM 	if ((strncmp(iscsiName, EUI, strlen(EUI)) != 0) &&
34157836SJohn.Forte@Sun.COM 	    strncmp(iscsiName, IQN, strlen(IQN)) != 0) {
34167836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
34177836SJohn.Forte@Sun.COM 	}
34187836SJohn.Forte@Sun.COM 
34197836SJohn.Forte@Sun.COM 	/* copy UTF-8 bytes to ident */
34207836SJohn.Forte@Sun.COM 	bcopy(iscsiName, devid->ident, devid->identLength);
34217836SJohn.Forte@Sun.COM 
34227836SJohn.Forte@Sun.COM 	return (STMF_STATUS_SUCCESS);
34237836SJohn.Forte@Sun.COM }
34247836SJohn.Forte@Sun.COM 
34257836SJohn.Forte@Sun.COM /*
34267836SJohn.Forte@Sun.COM  * stmfDevidFromWwn
34277836SJohn.Forte@Sun.COM  *
34287836SJohn.Forte@Sun.COM  * Purpose: convert a WWN to an stmf devid
34297836SJohn.Forte@Sun.COM  *
34307836SJohn.Forte@Sun.COM  * wwn - 8-byte wwn identifier
34317836SJohn.Forte@Sun.COM  * devid - on success, contains the converted wwn
34327836SJohn.Forte@Sun.COM  */
34337836SJohn.Forte@Sun.COM int
34347836SJohn.Forte@Sun.COM stmfDevidFromWwn(uchar_t *wwn, stmfDevid *devid)
34357836SJohn.Forte@Sun.COM {
34367836SJohn.Forte@Sun.COM 	if (wwn == NULL || devid == NULL)
34377836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
34387836SJohn.Forte@Sun.COM 
34397836SJohn.Forte@Sun.COM 	bzero(devid, sizeof (stmfDevid));
34407836SJohn.Forte@Sun.COM 
34417836SJohn.Forte@Sun.COM 	/* Copy eui prefix */
34427836SJohn.Forte@Sun.COM 	(void) bcopy(WWN, devid->ident, strlen(WWN));
34437836SJohn.Forte@Sun.COM 
34447836SJohn.Forte@Sun.COM 	/* Convert to ASCII uppercase hexadecimal string */
34457836SJohn.Forte@Sun.COM 	(void) snprintf((char *)&devid->ident[strlen(WWN)],
34467836SJohn.Forte@Sun.COM 	    sizeof (devid->ident), "%02X%02X%02X%02X%02X%02X%02X%02X",
34477836SJohn.Forte@Sun.COM 	    wwn[0], wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]);
34487836SJohn.Forte@Sun.COM 
34497836SJohn.Forte@Sun.COM 	devid->identLength = strlen((char *)devid->ident);
34507836SJohn.Forte@Sun.COM 
34517836SJohn.Forte@Sun.COM 	return (STMF_STATUS_SUCCESS);
34527836SJohn.Forte@Sun.COM }
34537836SJohn.Forte@Sun.COM 
34547836SJohn.Forte@Sun.COM /*
34557836SJohn.Forte@Sun.COM  * stmfFreeMemory
34567836SJohn.Forte@Sun.COM  *
34577836SJohn.Forte@Sun.COM  * Purpose: Free memory allocated by this library
34587836SJohn.Forte@Sun.COM  *
34597836SJohn.Forte@Sun.COM  * memory - previously allocated pointer of memory managed by library
34607836SJohn.Forte@Sun.COM  */
34617836SJohn.Forte@Sun.COM void
34627836SJohn.Forte@Sun.COM stmfFreeMemory(void *memory)
34637836SJohn.Forte@Sun.COM {
34647836SJohn.Forte@Sun.COM 	free(memory);
34657836SJohn.Forte@Sun.COM }
34667836SJohn.Forte@Sun.COM 
34677836SJohn.Forte@Sun.COM /*
34689585STim.Szeto@Sun.COM  * get host group, target group list from stmf
34697836SJohn.Forte@Sun.COM  *
34709585STim.Szeto@Sun.COM  * groupType - HOST_GROUP, TARGET_GROUP
34717836SJohn.Forte@Sun.COM  */
34729585STim.Szeto@Sun.COM static int
34739585STim.Szeto@Sun.COM groupListIoctl(stmfGroupList **groupList, int groupType)
34749585STim.Szeto@Sun.COM {
34759585STim.Szeto@Sun.COM 	int ret;
34769585STim.Szeto@Sun.COM 	int fd;
34779585STim.Szeto@Sun.COM 	int ioctlRet;
34789585STim.Szeto@Sun.COM 	int i;
34799585STim.Szeto@Sun.COM 	int cmd;
34809585STim.Szeto@Sun.COM 	stmf_iocdata_t stmfIoctl;
34819585STim.Szeto@Sun.COM 	/* framework group list */
34829585STim.Szeto@Sun.COM 	stmf_group_name_t *iGroupList = NULL;
34839585STim.Szeto@Sun.COM 	uint32_t groupListSize;
34849585STim.Szeto@Sun.COM 
34859585STim.Szeto@Sun.COM 	if (groupList == NULL) {
34869585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
34879585STim.Szeto@Sun.COM 	}
34889585STim.Szeto@Sun.COM 
34899585STim.Szeto@Sun.COM 	if (groupType == HOST_GROUP) {
34909585STim.Szeto@Sun.COM 		cmd = STMF_IOCTL_GET_HG_LIST;
34919585STim.Szeto@Sun.COM 	} else if (groupType == TARGET_GROUP) {
34929585STim.Szeto@Sun.COM 		cmd = STMF_IOCTL_GET_TG_LIST;
34939585STim.Szeto@Sun.COM 	} else {
34949585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
34959585STim.Szeto@Sun.COM 	}
34969585STim.Szeto@Sun.COM 
34979585STim.Szeto@Sun.COM 	/* call init */
34989585STim.Szeto@Sun.COM 	ret = initializeConfig();
34999585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
35009585STim.Szeto@Sun.COM 		return (ret);
35019585STim.Szeto@Sun.COM 	}
35029585STim.Szeto@Sun.COM 
35039585STim.Szeto@Sun.COM 	/*
35049585STim.Szeto@Sun.COM 	 * Open control node for stmf
35059585STim.Szeto@Sun.COM 	 */
35069585STim.Szeto@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
35079585STim.Szeto@Sun.COM 		return (ret);
35089585STim.Szeto@Sun.COM 
35099585STim.Szeto@Sun.COM 	/*
35109585STim.Szeto@Sun.COM 	 * Allocate ioctl input buffer
35119585STim.Szeto@Sun.COM 	 */
35129585STim.Szeto@Sun.COM 	groupListSize = ALLOC_GROUP;
35139585STim.Szeto@Sun.COM 	groupListSize = groupListSize * (sizeof (stmf_group_name_t));
35149585STim.Szeto@Sun.COM 	iGroupList = (stmf_group_name_t *)calloc(1, groupListSize);
35159585STim.Szeto@Sun.COM 	if (iGroupList == NULL) {
35169585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
35179585STim.Szeto@Sun.COM 		goto done;
35189585STim.Szeto@Sun.COM 	}
35199585STim.Szeto@Sun.COM 
35209585STim.Szeto@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
35219585STim.Szeto@Sun.COM 	/*
35229585STim.Szeto@Sun.COM 	 * Issue ioctl to get the group list
35239585STim.Szeto@Sun.COM 	 */
35249585STim.Szeto@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
35259585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf_size = groupListSize;
35269585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupList;
35279585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
35289585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
35299585STim.Szeto@Sun.COM 		switch (errno) {
35309585STim.Szeto@Sun.COM 			case EBUSY:
35319585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
35329585STim.Szeto@Sun.COM 				break;
35339585STim.Szeto@Sun.COM 			case EPERM:
35349585STim.Szeto@Sun.COM 			case EACCES:
35359585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
35369585STim.Szeto@Sun.COM 				break;
35379585STim.Szeto@Sun.COM 			default:
35389585STim.Szeto@Sun.COM 				syslog(LOG_DEBUG,
35399585STim.Szeto@Sun.COM 				    "groupListIoctl:ioctl errno(%d)",
35409585STim.Szeto@Sun.COM 				    errno);
35419585STim.Szeto@Sun.COM 				ret = STMF_STATUS_ERROR;
35429585STim.Szeto@Sun.COM 				break;
35439585STim.Szeto@Sun.COM 		}
35449585STim.Szeto@Sun.COM 		goto done;
35459585STim.Szeto@Sun.COM 	}
35469585STim.Szeto@Sun.COM 	/*
35479585STim.Szeto@Sun.COM 	 * Check whether input buffer was large enough
35489585STim.Szeto@Sun.COM 	 */
35499585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_GROUP) {
35509585STim.Szeto@Sun.COM 		groupListSize = stmfIoctl.stmf_obuf_max_nentries *
35519585STim.Szeto@Sun.COM 		    sizeof (stmf_group_name_t);
35529585STim.Szeto@Sun.COM 		iGroupList = realloc(iGroupList, groupListSize);
35539585STim.Szeto@Sun.COM 		if (iGroupList == NULL) {
35549585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NOMEM;
35559585STim.Szeto@Sun.COM 			goto done;
35569585STim.Szeto@Sun.COM 		}
35579585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf_size = groupListSize;
35589585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupList;
35599585STim.Szeto@Sun.COM 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
35609585STim.Szeto@Sun.COM 		if (ioctlRet != 0) {
35619585STim.Szeto@Sun.COM 			switch (errno) {
35629585STim.Szeto@Sun.COM 				case EBUSY:
35639585STim.Szeto@Sun.COM 					ret = STMF_ERROR_BUSY;
35649585STim.Szeto@Sun.COM 					break;
35659585STim.Szeto@Sun.COM 				case EPERM:
35669585STim.Szeto@Sun.COM 				case EACCES:
35679585STim.Szeto@Sun.COM 					ret = STMF_ERROR_PERM;
35689585STim.Szeto@Sun.COM 					break;
35699585STim.Szeto@Sun.COM 				default:
35709585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
35719585STim.Szeto@Sun.COM 					    "groupListIoctl:ioctl errno(%d)",
35729585STim.Szeto@Sun.COM 					    errno);
35739585STim.Szeto@Sun.COM 					ret = STMF_STATUS_ERROR;
35749585STim.Szeto@Sun.COM 					break;
35759585STim.Szeto@Sun.COM 			}
35769585STim.Szeto@Sun.COM 			goto done;
35779585STim.Szeto@Sun.COM 		}
35789585STim.Szeto@Sun.COM 	}
35799585STim.Szeto@Sun.COM 
35809585STim.Szeto@Sun.COM 	/* allocate and copy to caller's buffer */
358110236SSrivijitha.Dugganapalli@Sun.COM 	*groupList = (stmfGroupList *)calloc(1, sizeof (stmfGroupList) +
358210236SSrivijitha.Dugganapalli@Sun.COM 	    sizeof (stmfGroupName) * stmfIoctl.stmf_obuf_nentries);
35839585STim.Szeto@Sun.COM 	if (*groupList == NULL) {
35849585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
35859585STim.Szeto@Sun.COM 		goto done;
35869585STim.Szeto@Sun.COM 	}
35879585STim.Szeto@Sun.COM 	(*groupList)->cnt = stmfIoctl.stmf_obuf_nentries;
35889585STim.Szeto@Sun.COM 	for (i = 0; i < stmfIoctl.stmf_obuf_nentries; i++) {
358910113SNattuvetty.Bhavyan@Sun.COM 		bcopy(iGroupList[i].name, (*groupList)->name[i],
35909585STim.Szeto@Sun.COM 		    sizeof (stmfGroupName));
35919585STim.Szeto@Sun.COM 	}
35929585STim.Szeto@Sun.COM 
35939585STim.Szeto@Sun.COM done:
35949585STim.Szeto@Sun.COM 	free(iGroupList);
35959585STim.Szeto@Sun.COM 	(void) close(fd);
35969585STim.Szeto@Sun.COM 	return (ret);
35979585STim.Szeto@Sun.COM }
35989585STim.Szeto@Sun.COM 
35999585STim.Szeto@Sun.COM /*
36009585STim.Szeto@Sun.COM  * get host group members, target group members from stmf
36019585STim.Szeto@Sun.COM  *
36029585STim.Szeto@Sun.COM  * groupProps - allocated on success
36039585STim.Szeto@Sun.COM  *
36049585STim.Szeto@Sun.COM  * groupType - HOST_GROUP, TARGET_GROUP
36059585STim.Szeto@Sun.COM  */
36069585STim.Szeto@Sun.COM static int
36079585STim.Szeto@Sun.COM groupMemberListIoctl(stmfGroupName *groupName, stmfGroupProperties **groupProps,
36089585STim.Szeto@Sun.COM     int groupType)
36097836SJohn.Forte@Sun.COM {
36107836SJohn.Forte@Sun.COM 	int ret;
36119585STim.Szeto@Sun.COM 	int fd;
36129585STim.Szeto@Sun.COM 	int ioctlRet;
36139585STim.Szeto@Sun.COM 	int i;
36149585STim.Szeto@Sun.COM 	int cmd;
36159585STim.Szeto@Sun.COM 	stmf_iocdata_t stmfIoctl;
36169585STim.Szeto@Sun.COM 	/* framework group list */
36179585STim.Szeto@Sun.COM 	stmf_group_name_t iGroupName;
36189585STim.Szeto@Sun.COM 	stmf_ge_ident_t *iGroupMembers;
36199585STim.Szeto@Sun.COM 	uint32_t groupListSize;
36209585STim.Szeto@Sun.COM 
36219585STim.Szeto@Sun.COM 	if (groupName == NULL) {
36229585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
36239585STim.Szeto@Sun.COM 	}
36249585STim.Szeto@Sun.COM 
36259585STim.Szeto@Sun.COM 	if (groupType == HOST_GROUP) {
36269585STim.Szeto@Sun.COM 		cmd = STMF_IOCTL_GET_HG_ENTRIES;
36279585STim.Szeto@Sun.COM 	} else if (groupType == TARGET_GROUP) {
36289585STim.Szeto@Sun.COM 		cmd = STMF_IOCTL_GET_TG_ENTRIES;
36299585STim.Szeto@Sun.COM 	} else {
36307836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
36317836SJohn.Forte@Sun.COM 	}
36327836SJohn.Forte@Sun.COM 
36339585STim.Szeto@Sun.COM 	/* call init */
36349585STim.Szeto@Sun.COM 	ret = initializeConfig();
36359585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
36369585STim.Szeto@Sun.COM 		return (ret);
36379585STim.Szeto@Sun.COM 	}
36389585STim.Szeto@Sun.COM 
36399585STim.Szeto@Sun.COM 	/*
36409585STim.Szeto@Sun.COM 	 * Open control node for stmf
36419585STim.Szeto@Sun.COM 	 */
36429585STim.Szeto@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
36439585STim.Szeto@Sun.COM 		return (ret);
36449585STim.Szeto@Sun.COM 
36459585STim.Szeto@Sun.COM 	bzero(&iGroupName, sizeof (iGroupName));
36469585STim.Szeto@Sun.COM 
36479585STim.Szeto@Sun.COM 	bcopy(groupName, &iGroupName.name, strlen((char *)groupName));
36489585STim.Szeto@Sun.COM 
36499585STim.Szeto@Sun.COM 	iGroupName.name_size = strlen((char *)groupName);
36509585STim.Szeto@Sun.COM 
36519585STim.Szeto@Sun.COM 	/*
36529585STim.Szeto@Sun.COM 	 * Allocate ioctl input buffer
36539585STim.Szeto@Sun.COM 	 */
36549585STim.Szeto@Sun.COM 	groupListSize = ALLOC_GRP_MEMBER;
36559585STim.Szeto@Sun.COM 	groupListSize = groupListSize * (sizeof (stmf_ge_ident_t));
36569585STim.Szeto@Sun.COM 	iGroupMembers = (stmf_ge_ident_t *)calloc(1, groupListSize);
36579585STim.Szeto@Sun.COM 	if (iGroupMembers == NULL) {
36589585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
36599585STim.Szeto@Sun.COM 		goto done;
36609585STim.Szeto@Sun.COM 	}
36619585STim.Szeto@Sun.COM 
36629585STim.Szeto@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
36639585STim.Szeto@Sun.COM 	/*
36649585STim.Szeto@Sun.COM 	 * Issue ioctl to get the group list
36659585STim.Szeto@Sun.COM 	 */
36669585STim.Szeto@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
36679585STim.Szeto@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&iGroupName;
36689585STim.Szeto@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (stmf_group_name_t);
36699585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf_size = groupListSize;
36709585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupMembers;
36719585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
36729585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
36739585STim.Szeto@Sun.COM 		switch (errno) {
36749585STim.Szeto@Sun.COM 			case EBUSY:
36759585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
36769585STim.Szeto@Sun.COM 				break;
36779585STim.Szeto@Sun.COM 			case EPERM:
36789585STim.Szeto@Sun.COM 			case EACCES:
36799585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
36809585STim.Szeto@Sun.COM 				break;
36819585STim.Szeto@Sun.COM 			default:
36829585STim.Szeto@Sun.COM 				syslog(LOG_DEBUG,
36839585STim.Szeto@Sun.COM 				    "groupListIoctl:ioctl errno(%d)",
36849585STim.Szeto@Sun.COM 				    errno);
36859585STim.Szeto@Sun.COM 				ret = STMF_STATUS_ERROR;
36869585STim.Szeto@Sun.COM 				break;
36879585STim.Szeto@Sun.COM 		}
36889585STim.Szeto@Sun.COM 		goto done;
36899585STim.Szeto@Sun.COM 	}
36909585STim.Szeto@Sun.COM 	/*
36919585STim.Szeto@Sun.COM 	 * Check whether input buffer was large enough
36929585STim.Szeto@Sun.COM 	 */
36939585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_GRP_MEMBER) {
36949585STim.Szeto@Sun.COM 		groupListSize = stmfIoctl.stmf_obuf_max_nentries *
36959585STim.Szeto@Sun.COM 		    sizeof (stmf_ge_ident_t);
36969585STim.Szeto@Sun.COM 		iGroupMembers = realloc(iGroupMembers, groupListSize);
36979585STim.Szeto@Sun.COM 		if (iGroupMembers == NULL) {
36989585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NOMEM;
36999585STim.Szeto@Sun.COM 			goto done;
37009585STim.Szeto@Sun.COM 		}
37019585STim.Szeto@Sun.COM 		stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&iGroupName;
37029585STim.Szeto@Sun.COM 		stmfIoctl.stmf_ibuf_size = sizeof (stmf_group_name_t);
37039585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf_size = groupListSize;
37049585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupMembers;
37059585STim.Szeto@Sun.COM 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
37069585STim.Szeto@Sun.COM 		if (ioctlRet != 0) {
37079585STim.Szeto@Sun.COM 			switch (errno) {
37089585STim.Szeto@Sun.COM 				case EBUSY:
37099585STim.Szeto@Sun.COM 					ret = STMF_ERROR_BUSY;
37109585STim.Szeto@Sun.COM 					break;
37119585STim.Szeto@Sun.COM 				case EPERM:
37129585STim.Szeto@Sun.COM 				case EACCES:
37139585STim.Szeto@Sun.COM 					ret = STMF_ERROR_PERM;
37149585STim.Szeto@Sun.COM 					break;
37159585STim.Szeto@Sun.COM 				default:
37169585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
37179585STim.Szeto@Sun.COM 					    "groupListIoctl:ioctl errno(%d)",
37189585STim.Szeto@Sun.COM 					    errno);
37199585STim.Szeto@Sun.COM 					ret = STMF_STATUS_ERROR;
37209585STim.Szeto@Sun.COM 					break;
37219585STim.Szeto@Sun.COM 			}
37229585STim.Szeto@Sun.COM 			goto done;
37239585STim.Szeto@Sun.COM 		}
37249585STim.Szeto@Sun.COM 	}
37259585STim.Szeto@Sun.COM 
37269585STim.Szeto@Sun.COM 	/* allocate and copy to caller's buffer */
37279585STim.Szeto@Sun.COM 	*groupProps = (stmfGroupProperties *)calloc(1,
372810236SSrivijitha.Dugganapalli@Sun.COM 	    sizeof (stmfGroupProperties) +
372910236SSrivijitha.Dugganapalli@Sun.COM 	    sizeof (stmfDevid) * stmfIoctl.stmf_obuf_nentries);
37309585STim.Szeto@Sun.COM 	if (*groupProps == NULL) {
37319585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
37329585STim.Szeto@Sun.COM 		goto done;
37339585STim.Szeto@Sun.COM 	}
37349585STim.Szeto@Sun.COM 	(*groupProps)->cnt = stmfIoctl.stmf_obuf_nentries;
37359585STim.Szeto@Sun.COM 	for (i = 0; i < stmfIoctl.stmf_obuf_nentries; i++) {
37369585STim.Szeto@Sun.COM 		(*groupProps)->name[i].identLength =
373710113SNattuvetty.Bhavyan@Sun.COM 		    iGroupMembers[i].ident_size;
373810113SNattuvetty.Bhavyan@Sun.COM 		bcopy(iGroupMembers[i].ident, (*groupProps)->name[i].ident,
373910113SNattuvetty.Bhavyan@Sun.COM 		    iGroupMembers[i].ident_size);
37409585STim.Szeto@Sun.COM 	}
37419585STim.Szeto@Sun.COM 
37429585STim.Szeto@Sun.COM done:
37439585STim.Szeto@Sun.COM 	free(iGroupMembers);
37449585STim.Szeto@Sun.COM 	(void) close(fd);
37459585STim.Szeto@Sun.COM 	return (ret);
37469585STim.Szeto@Sun.COM }
37479585STim.Szeto@Sun.COM 
37489585STim.Szeto@Sun.COM /*
37499585STim.Szeto@Sun.COM  * Purpose: access persistent config data for host groups and target groups
37509585STim.Szeto@Sun.COM  */
37519585STim.Szeto@Sun.COM static int
37529585STim.Szeto@Sun.COM iLoadGroupFromPs(stmfGroupList **groupList, int type)
37539585STim.Szeto@Sun.COM {
37549585STim.Szeto@Sun.COM 	int ret;
37559585STim.Szeto@Sun.COM 
37569585STim.Szeto@Sun.COM 	if (groupList == NULL) {
37579585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
37589585STim.Szeto@Sun.COM 	}
37599585STim.Szeto@Sun.COM 
37609585STim.Szeto@Sun.COM 	if (type == HOST_GROUP) {
37619585STim.Szeto@Sun.COM 		ret = psGetHostGroupList(groupList);
37629585STim.Szeto@Sun.COM 	} else if (type == TARGET_GROUP) {
37639585STim.Szeto@Sun.COM 		ret = psGetTargetGroupList(groupList);
37649585STim.Szeto@Sun.COM 	} else {
37659585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
37669585STim.Szeto@Sun.COM 	}
37677836SJohn.Forte@Sun.COM 	switch (ret) {
37687836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
37697836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
37707836SJohn.Forte@Sun.COM 			break;
37717836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
37727836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
37737836SJohn.Forte@Sun.COM 			break;
37747836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
37757836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
37767836SJohn.Forte@Sun.COM 			break;
37777836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
37787836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
37797836SJohn.Forte@Sun.COM 			break;
37807836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
37817836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
37827836SJohn.Forte@Sun.COM 			break;
37837836SJohn.Forte@Sun.COM 		default:
37847836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
37857836SJohn.Forte@Sun.COM 			    "stmfGetHostGroupList:psGetHostGroupList:error(%d)",
37867836SJohn.Forte@Sun.COM 			    ret);
37877836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
37887836SJohn.Forte@Sun.COM 			break;
37897836SJohn.Forte@Sun.COM 	}
37907836SJohn.Forte@Sun.COM 
37917836SJohn.Forte@Sun.COM 	return (ret);
37927836SJohn.Forte@Sun.COM }
37937836SJohn.Forte@Sun.COM 
37947836SJohn.Forte@Sun.COM /*
37959585STim.Szeto@Sun.COM  * stmfGetHostGroupList
37967836SJohn.Forte@Sun.COM  *
37979585STim.Szeto@Sun.COM  * Purpose: Retrieves the list of initiator group oids
37989585STim.Szeto@Sun.COM  *
37999585STim.Szeto@Sun.COM  * hostGroupList - pointer to pointer to hostGroupList structure
38009585STim.Szeto@Sun.COM  *                 on success, this contains the host group list.
38017836SJohn.Forte@Sun.COM  */
38027836SJohn.Forte@Sun.COM int
38039585STim.Szeto@Sun.COM stmfGetHostGroupList(stmfGroupList **hostGroupList)
38049585STim.Szeto@Sun.COM {
38059585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_ERROR;
38069585STim.Szeto@Sun.COM 
38079585STim.Szeto@Sun.COM 	if (hostGroupList == NULL) {
38089585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
38099585STim.Szeto@Sun.COM 	}
38109585STim.Szeto@Sun.COM 
38119585STim.Szeto@Sun.COM 	ret = groupListIoctl(hostGroupList, HOST_GROUP);
38129585STim.Szeto@Sun.COM 	return (ret);
38139585STim.Szeto@Sun.COM }
38149585STim.Szeto@Sun.COM 
38159585STim.Szeto@Sun.COM 
38169585STim.Szeto@Sun.COM /*
38179585STim.Szeto@Sun.COM  * Purpose: access persistent config data for host groups and target groups
38189585STim.Szeto@Sun.COM  */
38199585STim.Szeto@Sun.COM static int
38209585STim.Szeto@Sun.COM iLoadGroupMembersFromPs(stmfGroupName *groupName,
38219585STim.Szeto@Sun.COM     stmfGroupProperties **groupProp, int type)
38227836SJohn.Forte@Sun.COM {
38237836SJohn.Forte@Sun.COM 	int ret;
38247836SJohn.Forte@Sun.COM 
38259585STim.Szeto@Sun.COM 	if (groupName == NULL) {
38267836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
38277836SJohn.Forte@Sun.COM 	}
38287836SJohn.Forte@Sun.COM 
38299585STim.Szeto@Sun.COM 	if (type == HOST_GROUP) {
38309585STim.Szeto@Sun.COM 		ret = psGetHostGroupMemberList((char *)groupName, groupProp);
38319585STim.Szeto@Sun.COM 	} else if (type == TARGET_GROUP) {
38329585STim.Szeto@Sun.COM 		ret = psGetTargetGroupMemberList((char *)groupName, groupProp);
38339585STim.Szeto@Sun.COM 	} else {
38349585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
38359585STim.Szeto@Sun.COM 	}
38367836SJohn.Forte@Sun.COM 	switch (ret) {
38377836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
38387836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
38397836SJohn.Forte@Sun.COM 			break;
38407836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
38417836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
38427836SJohn.Forte@Sun.COM 			break;
38437836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
38447836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
38457836SJohn.Forte@Sun.COM 			break;
38467836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
38477836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
38487836SJohn.Forte@Sun.COM 			break;
38497836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
38507836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
38517836SJohn.Forte@Sun.COM 			break;
38527836SJohn.Forte@Sun.COM 		default:
38537836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
38549585STim.Szeto@Sun.COM 			    "iLoadGroupMembersFromPs:psGetHostGroupList:"
38559585STim.Szeto@Sun.COM 			    "error(%d)", ret);
38567836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
38577836SJohn.Forte@Sun.COM 			break;
38587836SJohn.Forte@Sun.COM 	}
38597836SJohn.Forte@Sun.COM 
38607836SJohn.Forte@Sun.COM 	return (ret);
38617836SJohn.Forte@Sun.COM }
38627836SJohn.Forte@Sun.COM 
38637836SJohn.Forte@Sun.COM /*
38649585STim.Szeto@Sun.COM  * stmfGetHostGroupMembers
38659585STim.Szeto@Sun.COM  *
38669585STim.Szeto@Sun.COM  * Purpose: Retrieves the group properties for a host group
38679585STim.Szeto@Sun.COM  *
38689585STim.Szeto@Sun.COM  * groupName - name of group for which to retrieve host group members.
38699585STim.Szeto@Sun.COM  * groupProp - pointer to pointer to stmfGroupProperties structure
38709585STim.Szeto@Sun.COM  *             on success, this contains the list of group members.
38719585STim.Szeto@Sun.COM  */
38729585STim.Szeto@Sun.COM int
38739585STim.Szeto@Sun.COM stmfGetHostGroupMembers(stmfGroupName *groupName,
38749585STim.Szeto@Sun.COM     stmfGroupProperties **groupProp)
38759585STim.Szeto@Sun.COM {
38769585STim.Szeto@Sun.COM 	int ret;
38779585STim.Szeto@Sun.COM 
38789585STim.Szeto@Sun.COM 	if (groupName == NULL || groupProp == NULL) {
38799585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
38809585STim.Szeto@Sun.COM 	}
38819585STim.Szeto@Sun.COM 
38829585STim.Szeto@Sun.COM 	ret = groupMemberListIoctl(groupName, groupProp, HOST_GROUP);
38839585STim.Szeto@Sun.COM 
38849585STim.Szeto@Sun.COM 	return (ret);
38859585STim.Szeto@Sun.COM }
38869585STim.Szeto@Sun.COM 
38879585STim.Szeto@Sun.COM /*
38887836SJohn.Forte@Sun.COM  * stmfGetProviderData
38897836SJohn.Forte@Sun.COM  *
38907836SJohn.Forte@Sun.COM  * Purpose: Get provider data list
38917836SJohn.Forte@Sun.COM  *
38927836SJohn.Forte@Sun.COM  * providerName - name of provider for which to retrieve the data
38937836SJohn.Forte@Sun.COM  * nvl - pointer to nvlist_t pointer which will contain the nvlist data
38947836SJohn.Forte@Sun.COM  *       retrieved.
38957836SJohn.Forte@Sun.COM  * providerType - type of provider for which to retrieve data.
38967836SJohn.Forte@Sun.COM  *		    STMF_LU_PROVIDER_TYPE
38977836SJohn.Forte@Sun.COM  *		    STMF_PORT_PROVIDER_TYPE
38987836SJohn.Forte@Sun.COM  */
38997836SJohn.Forte@Sun.COM int
39007836SJohn.Forte@Sun.COM stmfGetProviderData(char *providerName, nvlist_t **nvl, int providerType)
39017836SJohn.Forte@Sun.COM {
39027836SJohn.Forte@Sun.COM 	return (stmfGetProviderDataProt(providerName, nvl, providerType,
39037836SJohn.Forte@Sun.COM 	    NULL));
39047836SJohn.Forte@Sun.COM }
39057836SJohn.Forte@Sun.COM 
39067836SJohn.Forte@Sun.COM /*
39077836SJohn.Forte@Sun.COM  * stmfGetProviderDataProt
39087836SJohn.Forte@Sun.COM  *
39097836SJohn.Forte@Sun.COM  * Purpose: Get provider data list with token
39107836SJohn.Forte@Sun.COM  *
39117836SJohn.Forte@Sun.COM  * providerName - name of provider for which to retrieve the data
39127836SJohn.Forte@Sun.COM  * nvl - pointer to nvlist_t pointer which will contain the nvlist data
39137836SJohn.Forte@Sun.COM  *       retrieved.
39147836SJohn.Forte@Sun.COM  * providerType - type of provider for which to retrieve data.
39157836SJohn.Forte@Sun.COM  *		    STMF_LU_PROVIDER_TYPE
39167836SJohn.Forte@Sun.COM  *		    STMF_PORT_PROVIDER_TYPE
39177836SJohn.Forte@Sun.COM  * setToken - Returns the stale data token
39187836SJohn.Forte@Sun.COM  */
39197836SJohn.Forte@Sun.COM int
39207836SJohn.Forte@Sun.COM stmfGetProviderDataProt(char *providerName, nvlist_t **nvl, int providerType,
39217836SJohn.Forte@Sun.COM     uint64_t *setToken)
39227836SJohn.Forte@Sun.COM {
39237836SJohn.Forte@Sun.COM 	int ret;
39247836SJohn.Forte@Sun.COM 
39257836SJohn.Forte@Sun.COM 	if (providerName == NULL || nvl == NULL) {
39267836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
39277836SJohn.Forte@Sun.COM 	}
39287836SJohn.Forte@Sun.COM 	if (providerType != STMF_LU_PROVIDER_TYPE &&
39297836SJohn.Forte@Sun.COM 	    providerType != STMF_PORT_PROVIDER_TYPE) {
39307836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
39317836SJohn.Forte@Sun.COM 	}
39327836SJohn.Forte@Sun.COM 	/* call init */
39337836SJohn.Forte@Sun.COM 	ret = initializeConfig();
39347836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
39357836SJohn.Forte@Sun.COM 		return (ret);
39367836SJohn.Forte@Sun.COM 	}
39379585STim.Szeto@Sun.COM 	return (getProviderData(providerName, nvl, providerType, setToken));
39387836SJohn.Forte@Sun.COM }
39397836SJohn.Forte@Sun.COM 
39407836SJohn.Forte@Sun.COM /*
39417836SJohn.Forte@Sun.COM  * stmfGetProviderDataList
39427836SJohn.Forte@Sun.COM  *
39437836SJohn.Forte@Sun.COM  * Purpose: Get the list of providers currently persisting data
39447836SJohn.Forte@Sun.COM  *
39457836SJohn.Forte@Sun.COM  * providerList - pointer to pointer to an stmfProviderList structure allocated
39467836SJohn.Forte@Sun.COM  *                by the caller. Will contain the list of providers on success.
39477836SJohn.Forte@Sun.COM  */
39487836SJohn.Forte@Sun.COM int
39497836SJohn.Forte@Sun.COM stmfGetProviderDataList(stmfProviderList **providerList)
39507836SJohn.Forte@Sun.COM {
39517836SJohn.Forte@Sun.COM 	int ret;
39527836SJohn.Forte@Sun.COM 
39537836SJohn.Forte@Sun.COM 	ret = psGetProviderDataList(providerList);
39547836SJohn.Forte@Sun.COM 	switch (ret) {
39557836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
39567836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
39577836SJohn.Forte@Sun.COM 			break;
39587836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
39597836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
39607836SJohn.Forte@Sun.COM 			break;
39617836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
39627836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
39637836SJohn.Forte@Sun.COM 			break;
39647836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
39657836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
39667836SJohn.Forte@Sun.COM 			break;
39677836SJohn.Forte@Sun.COM 		default:
39687836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
39697836SJohn.Forte@Sun.COM 			    "stmfGetProviderDataList:psGetProviderDataList"
39707836SJohn.Forte@Sun.COM 			    ":error(%d)", ret);
39717836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
39727836SJohn.Forte@Sun.COM 			break;
39737836SJohn.Forte@Sun.COM 	}
39747836SJohn.Forte@Sun.COM 
39757836SJohn.Forte@Sun.COM 	return (ret);
39767836SJohn.Forte@Sun.COM }
39777836SJohn.Forte@Sun.COM 
39787836SJohn.Forte@Sun.COM 
39797836SJohn.Forte@Sun.COM /*
39807836SJohn.Forte@Sun.COM  * stmfGetSessionList
39817836SJohn.Forte@Sun.COM  *
39827836SJohn.Forte@Sun.COM  * Purpose: Retrieves the session list for a target (devid)
39837836SJohn.Forte@Sun.COM  *
39847836SJohn.Forte@Sun.COM  * devid - devid of target for which to retrieve session information.
39857836SJohn.Forte@Sun.COM  * sessionList - pointer to pointer to stmfSessionList structure
39867836SJohn.Forte@Sun.COM  *             on success, this contains the list of initiator sessions.
39877836SJohn.Forte@Sun.COM  */
39887836SJohn.Forte@Sun.COM int
39897836SJohn.Forte@Sun.COM stmfGetSessionList(stmfDevid *devid, stmfSessionList **sessionList)
39907836SJohn.Forte@Sun.COM {
39917836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
39927836SJohn.Forte@Sun.COM 	int fd;
39937836SJohn.Forte@Sun.COM 	int ioctlRet;
39947836SJohn.Forte@Sun.COM 	int cmd = STMF_IOCTL_SESSION_LIST;
39957836SJohn.Forte@Sun.COM 	int i;
39967836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
399710261SCharles.Ting@Sun.COM 	slist_scsi_session_t *fSessionList, *fSessionListP = NULL;
39987836SJohn.Forte@Sun.COM 	uint8_t ident[260];
39997836SJohn.Forte@Sun.COM 	uint32_t fSessionListSize;
40007836SJohn.Forte@Sun.COM 
40017836SJohn.Forte@Sun.COM 	if (sessionList == NULL || devid == NULL) {
40027836SJohn.Forte@Sun.COM 		ret = STMF_ERROR_INVALID_ARG;
40037836SJohn.Forte@Sun.COM 	}
40047836SJohn.Forte@Sun.COM 
40057836SJohn.Forte@Sun.COM 	/* call init */
40067836SJohn.Forte@Sun.COM 	ret = initializeConfig();
40077836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
40087836SJohn.Forte@Sun.COM 		return (ret);
40097836SJohn.Forte@Sun.COM 	}
40107836SJohn.Forte@Sun.COM 
40117836SJohn.Forte@Sun.COM 	/*
40127836SJohn.Forte@Sun.COM 	 * Open control node for stmf
40137836SJohn.Forte@Sun.COM 	 */
40147836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
40157836SJohn.Forte@Sun.COM 		return (ret);
40167836SJohn.Forte@Sun.COM 
40177836SJohn.Forte@Sun.COM 	/*
40187836SJohn.Forte@Sun.COM 	 * Allocate ioctl input buffer
40197836SJohn.Forte@Sun.COM 	 */
40209585STim.Szeto@Sun.COM 	fSessionListSize = ALLOC_SESSION;
40217836SJohn.Forte@Sun.COM 	fSessionListSize = fSessionListSize * (sizeof (slist_scsi_session_t));
40227836SJohn.Forte@Sun.COM 	fSessionList = (slist_scsi_session_t *)calloc(1, fSessionListSize);
402310261SCharles.Ting@Sun.COM 	fSessionListP = fSessionList;
40247836SJohn.Forte@Sun.COM 	if (fSessionList == NULL) {
402510261SCharles.Ting@Sun.COM 		ret = STMF_ERROR_NOMEM;
402610261SCharles.Ting@Sun.COM 		goto done;
40277836SJohn.Forte@Sun.COM 	}
40287836SJohn.Forte@Sun.COM 
40297836SJohn.Forte@Sun.COM 	ident[IDENT_LENGTH_BYTE] = devid->identLength;
40307836SJohn.Forte@Sun.COM 	bcopy(&(devid->ident), &ident[IDENT_LENGTH_BYTE + 1],
40317836SJohn.Forte@Sun.COM 	    devid->identLength);
40327836SJohn.Forte@Sun.COM 
40337836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
40347836SJohn.Forte@Sun.COM 	/*
40357836SJohn.Forte@Sun.COM 	 * Issue ioctl to get the session list
40367836SJohn.Forte@Sun.COM 	 */
40377836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
40387836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ident;
40397836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (ident);
40407836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = fSessionListSize;
40417836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fSessionList;
40427836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
40437836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
40447836SJohn.Forte@Sun.COM 		switch (errno) {
40457836SJohn.Forte@Sun.COM 			case EBUSY:
40467836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
40477836SJohn.Forte@Sun.COM 				break;
40489585STim.Szeto@Sun.COM 			case EPERM:
40497836SJohn.Forte@Sun.COM 			case EACCES:
40507836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
40517836SJohn.Forte@Sun.COM 				break;
40527836SJohn.Forte@Sun.COM 			default:
40537836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
40547836SJohn.Forte@Sun.COM 				    "stmfGetSessionList:ioctl errno(%d)",
40557836SJohn.Forte@Sun.COM 				    errno);
40567836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
40577836SJohn.Forte@Sun.COM 				break;
40587836SJohn.Forte@Sun.COM 		}
40597836SJohn.Forte@Sun.COM 		goto done;
40607836SJohn.Forte@Sun.COM 	}
40617836SJohn.Forte@Sun.COM 	/*
40627836SJohn.Forte@Sun.COM 	 * Check whether input buffer was large enough
40637836SJohn.Forte@Sun.COM 	 */
40649585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_SESSION) {
40657836SJohn.Forte@Sun.COM 		fSessionListSize = stmfIoctl.stmf_obuf_max_nentries *
40667836SJohn.Forte@Sun.COM 		    sizeof (slist_scsi_session_t);
40677836SJohn.Forte@Sun.COM 		fSessionList = realloc(fSessionList, fSessionListSize);
40687836SJohn.Forte@Sun.COM 		if (fSessionList == NULL) {
406910261SCharles.Ting@Sun.COM 			ret = STMF_ERROR_NOMEM;
407010261SCharles.Ting@Sun.COM 			goto done;
40717836SJohn.Forte@Sun.COM 		}
407210261SCharles.Ting@Sun.COM 		fSessionListP = fSessionList;
40737836SJohn.Forte@Sun.COM 		stmfIoctl.stmf_obuf_size = fSessionListSize;
40747836SJohn.Forte@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fSessionList;
40757836SJohn.Forte@Sun.COM 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
40767836SJohn.Forte@Sun.COM 		if (ioctlRet != 0) {
40777836SJohn.Forte@Sun.COM 			switch (errno) {
40787836SJohn.Forte@Sun.COM 				case EBUSY:
40797836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_BUSY;
40807836SJohn.Forte@Sun.COM 					break;
40819585STim.Szeto@Sun.COM 				case EPERM:
40827836SJohn.Forte@Sun.COM 				case EACCES:
40837836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_PERM;
40847836SJohn.Forte@Sun.COM 					break;
40857836SJohn.Forte@Sun.COM 				default:
40867836SJohn.Forte@Sun.COM 					syslog(LOG_DEBUG,
40877836SJohn.Forte@Sun.COM 					    "stmfGetSessionList:ioctl "
40887836SJohn.Forte@Sun.COM 					    "errno(%d)", errno);
40897836SJohn.Forte@Sun.COM 					ret = STMF_STATUS_ERROR;
40907836SJohn.Forte@Sun.COM 					break;
40917836SJohn.Forte@Sun.COM 			}
40927836SJohn.Forte@Sun.COM 			goto done;
40937836SJohn.Forte@Sun.COM 		}
40947836SJohn.Forte@Sun.COM 	}
40957836SJohn.Forte@Sun.COM 
40967836SJohn.Forte@Sun.COM 	/*
40977836SJohn.Forte@Sun.COM 	 * allocate caller's buffer with the final size
40987836SJohn.Forte@Sun.COM 	 */
40997836SJohn.Forte@Sun.COM 	*sessionList = (stmfSessionList *)calloc(1, sizeof (stmfSessionList) +
41007836SJohn.Forte@Sun.COM 	    stmfIoctl.stmf_obuf_max_nentries * sizeof (stmfSession));
41017836SJohn.Forte@Sun.COM 	if (*sessionList == NULL) {
41027836SJohn.Forte@Sun.COM 		ret = STMF_ERROR_NOMEM;
41037836SJohn.Forte@Sun.COM 		free(sessionList);
41047836SJohn.Forte@Sun.COM 		goto done;
41057836SJohn.Forte@Sun.COM 	}
41067836SJohn.Forte@Sun.COM 
41077836SJohn.Forte@Sun.COM 	(*sessionList)->cnt = stmfIoctl.stmf_obuf_max_nentries;
41087836SJohn.Forte@Sun.COM 
41097836SJohn.Forte@Sun.COM 	/*
41107836SJohn.Forte@Sun.COM 	 * copy session info to caller's buffer
41117836SJohn.Forte@Sun.COM 	 */
41127836SJohn.Forte@Sun.COM 	for (i = 0; i < (*sessionList)->cnt; i++) {
41137836SJohn.Forte@Sun.COM 		(*sessionList)->session[i].initiator.identLength =
41147836SJohn.Forte@Sun.COM 		    fSessionList->initiator[IDENT_LENGTH_BYTE];
41157836SJohn.Forte@Sun.COM 		bcopy(&(fSessionList->initiator[IDENT_LENGTH_BYTE + 1]),
41167836SJohn.Forte@Sun.COM 		    (*sessionList)->session[i].initiator.ident,
41177836SJohn.Forte@Sun.COM 		    STMF_IDENT_LENGTH);
41187836SJohn.Forte@Sun.COM 		bcopy(&(fSessionList->alias),
41197836SJohn.Forte@Sun.COM 		    &((*sessionList)->session[i].alias),
41207836SJohn.Forte@Sun.COM 		    sizeof ((*sessionList)->session[i].alias));
41217836SJohn.Forte@Sun.COM 		bcopy(&(fSessionList++->creation_time),
41227836SJohn.Forte@Sun.COM 		    &((*sessionList)->session[i].creationTime),
41237836SJohn.Forte@Sun.COM 		    sizeof (time_t));
41247836SJohn.Forte@Sun.COM 	}
41257836SJohn.Forte@Sun.COM done:
41267836SJohn.Forte@Sun.COM 	(void) close(fd);
412710261SCharles.Ting@Sun.COM 	free(fSessionListP);
41287836SJohn.Forte@Sun.COM 	return (ret);
41297836SJohn.Forte@Sun.COM }
41307836SJohn.Forte@Sun.COM 
41317836SJohn.Forte@Sun.COM /*
41327836SJohn.Forte@Sun.COM  * stmfGetTargetGroupList
41337836SJohn.Forte@Sun.COM  *
41347836SJohn.Forte@Sun.COM  * Purpose: Retrieves the list of target groups
41357836SJohn.Forte@Sun.COM  *
41367836SJohn.Forte@Sun.COM  * targetGroupList - pointer to a pointer to an stmfGroupList structure. On
41377836SJohn.Forte@Sun.COM  *		     success, it contains the list of target groups.
41387836SJohn.Forte@Sun.COM  */
41397836SJohn.Forte@Sun.COM int
41407836SJohn.Forte@Sun.COM stmfGetTargetGroupList(stmfGroupList **targetGroupList)
41417836SJohn.Forte@Sun.COM {
41427836SJohn.Forte@Sun.COM 	int ret;
41437836SJohn.Forte@Sun.COM 
41447836SJohn.Forte@Sun.COM 	if (targetGroupList == NULL) {
41457836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
41467836SJohn.Forte@Sun.COM 	}
41477836SJohn.Forte@Sun.COM 
41489585STim.Szeto@Sun.COM 	ret = groupListIoctl(targetGroupList, TARGET_GROUP);
41497836SJohn.Forte@Sun.COM 	return (ret);
41507836SJohn.Forte@Sun.COM }
41517836SJohn.Forte@Sun.COM 
41527836SJohn.Forte@Sun.COM /*
41537836SJohn.Forte@Sun.COM  * stmfGetTargetGroupMembers
41547836SJohn.Forte@Sun.COM  *
41557836SJohn.Forte@Sun.COM  * Purpose: Retrieves the group members for a target group
41567836SJohn.Forte@Sun.COM  *
41577836SJohn.Forte@Sun.COM  * groupName - name of target group for which to retrieve members.
41587836SJohn.Forte@Sun.COM  * groupProp - pointer to pointer to stmfGroupProperties structure
41597836SJohn.Forte@Sun.COM  *             on success, this contains the list of group members.
41607836SJohn.Forte@Sun.COM  */
41617836SJohn.Forte@Sun.COM int
41627836SJohn.Forte@Sun.COM stmfGetTargetGroupMembers(stmfGroupName *groupName,
41637836SJohn.Forte@Sun.COM     stmfGroupProperties **groupProp)
41647836SJohn.Forte@Sun.COM {
41657836SJohn.Forte@Sun.COM 	int ret;
41667836SJohn.Forte@Sun.COM 
41677836SJohn.Forte@Sun.COM 	if (groupName == NULL || groupProp == NULL) {
41687836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
41697836SJohn.Forte@Sun.COM 	}
41707836SJohn.Forte@Sun.COM 
41719585STim.Szeto@Sun.COM 	ret = groupMemberListIoctl(groupName, groupProp, TARGET_GROUP);
41727836SJohn.Forte@Sun.COM 
41737836SJohn.Forte@Sun.COM 	return (ret);
41747836SJohn.Forte@Sun.COM }
41757836SJohn.Forte@Sun.COM 
41767836SJohn.Forte@Sun.COM /*
41777836SJohn.Forte@Sun.COM  * stmfGetTargetList
41787836SJohn.Forte@Sun.COM  *
41797836SJohn.Forte@Sun.COM  * Purpose: Retrieves the list of target ports
41807836SJohn.Forte@Sun.COM  *
41817836SJohn.Forte@Sun.COM  * targetList - pointer to a pointer to an stmfDevidList structure.
41827836SJohn.Forte@Sun.COM  *		    On success, it contains the list of local ports (target).
41837836SJohn.Forte@Sun.COM  */
41847836SJohn.Forte@Sun.COM int
41857836SJohn.Forte@Sun.COM stmfGetTargetList(stmfDevidList **targetList)
41867836SJohn.Forte@Sun.COM {
41877836SJohn.Forte@Sun.COM 	int ret;
41887836SJohn.Forte@Sun.COM 	int fd;
41897836SJohn.Forte@Sun.COM 	int ioctlRet;
41907836SJohn.Forte@Sun.COM 	int i;
41917836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
41927836SJohn.Forte@Sun.COM 	/* framework target port list */
41939585STim.Szeto@Sun.COM 	slist_target_port_t *fTargetList, *fTargetListP = NULL;
41947836SJohn.Forte@Sun.COM 	uint32_t fTargetListSize;
41957836SJohn.Forte@Sun.COM 
41967836SJohn.Forte@Sun.COM 	if (targetList == NULL) {
41977836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
41987836SJohn.Forte@Sun.COM 	}
41997836SJohn.Forte@Sun.COM 
42007836SJohn.Forte@Sun.COM 	/* call init */
42017836SJohn.Forte@Sun.COM 	ret = initializeConfig();
42027836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
42037836SJohn.Forte@Sun.COM 		return (ret);
42047836SJohn.Forte@Sun.COM 	}
42057836SJohn.Forte@Sun.COM 
42067836SJohn.Forte@Sun.COM 	/*
42077836SJohn.Forte@Sun.COM 	 * Open control node for stmf
42087836SJohn.Forte@Sun.COM 	 */
42097836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
42107836SJohn.Forte@Sun.COM 		return (ret);
42117836SJohn.Forte@Sun.COM 
42127836SJohn.Forte@Sun.COM 	/*
42137836SJohn.Forte@Sun.COM 	 * Allocate ioctl input buffer
42147836SJohn.Forte@Sun.COM 	 */
42159585STim.Szeto@Sun.COM 	fTargetListSize = ALLOC_TARGET_PORT * sizeof (slist_target_port_t);
42168252SJohn.Forte@Sun.COM 	fTargetListP = fTargetList =
42178252SJohn.Forte@Sun.COM 	    (slist_target_port_t *)calloc(1, fTargetListSize);
42187836SJohn.Forte@Sun.COM 	if (fTargetList == NULL) {
42199585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
42207836SJohn.Forte@Sun.COM 		goto done;
42217836SJohn.Forte@Sun.COM 	}
42227836SJohn.Forte@Sun.COM 
42237836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
42247836SJohn.Forte@Sun.COM 	/*
42258252SJohn.Forte@Sun.COM 	 * Issue ioctl to retrieve target list
42267836SJohn.Forte@Sun.COM 	 */
42277836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
42287836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = fTargetListSize;
42297836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fTargetList;
42307836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_TARGET_PORT_LIST, &stmfIoctl);
42317836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
42327836SJohn.Forte@Sun.COM 		switch (errno) {
42337836SJohn.Forte@Sun.COM 			case EBUSY:
42347836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
42357836SJohn.Forte@Sun.COM 				break;
42369585STim.Szeto@Sun.COM 			case EPERM:
42377836SJohn.Forte@Sun.COM 			case EACCES:
42387836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
42397836SJohn.Forte@Sun.COM 				break;
42407836SJohn.Forte@Sun.COM 			default:
42417836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
42427836SJohn.Forte@Sun.COM 				    "stmfGetTargetList:ioctl errno(%d)", errno);
42437836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
42447836SJohn.Forte@Sun.COM 				break;
42457836SJohn.Forte@Sun.COM 		}
42467836SJohn.Forte@Sun.COM 		goto done;
42477836SJohn.Forte@Sun.COM 	}
42487836SJohn.Forte@Sun.COM 	/*
42497836SJohn.Forte@Sun.COM 	 * Check whether input buffer was large enough
42507836SJohn.Forte@Sun.COM 	 */
42519585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_TARGET_PORT) {
42527836SJohn.Forte@Sun.COM 		fTargetListSize = stmfIoctl.stmf_obuf_max_nentries *
42538116SJohn.Forte@Sun.COM 		    sizeof (slist_target_port_t);
42548252SJohn.Forte@Sun.COM 		fTargetListP = fTargetList =
42558252SJohn.Forte@Sun.COM 		    realloc(fTargetList, fTargetListSize);
42567836SJohn.Forte@Sun.COM 		if (fTargetList == NULL) {
42579585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NOMEM;
42589585STim.Szeto@Sun.COM 			goto done;
42597836SJohn.Forte@Sun.COM 		}
42607836SJohn.Forte@Sun.COM 		stmfIoctl.stmf_obuf_size = fTargetListSize;
42617836SJohn.Forte@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fTargetList;
42627836SJohn.Forte@Sun.COM 		ioctlRet = ioctl(fd, STMF_IOCTL_TARGET_PORT_LIST,
42637836SJohn.Forte@Sun.COM 		    &stmfIoctl);
42647836SJohn.Forte@Sun.COM 		if (ioctlRet != 0) {
42657836SJohn.Forte@Sun.COM 			switch (errno) {
42667836SJohn.Forte@Sun.COM 				case EBUSY:
42677836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_BUSY;
42687836SJohn.Forte@Sun.COM 					break;
42699585STim.Szeto@Sun.COM 				case EPERM:
42707836SJohn.Forte@Sun.COM 				case EACCES:
42717836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_PERM;
42727836SJohn.Forte@Sun.COM 					break;
42737836SJohn.Forte@Sun.COM 				default:
42747836SJohn.Forte@Sun.COM 					syslog(LOG_DEBUG,
42757836SJohn.Forte@Sun.COM 					    "stmfGetTargetList:ioctl errno(%d)",
42767836SJohn.Forte@Sun.COM 					    errno);
42777836SJohn.Forte@Sun.COM 					ret = STMF_STATUS_ERROR;
42787836SJohn.Forte@Sun.COM 					break;
42797836SJohn.Forte@Sun.COM 			}
42807836SJohn.Forte@Sun.COM 			goto done;
42817836SJohn.Forte@Sun.COM 		}
42827836SJohn.Forte@Sun.COM 	}
42837836SJohn.Forte@Sun.COM 
42847836SJohn.Forte@Sun.COM 	*targetList = (stmfDevidList *)calloc(1,
42857836SJohn.Forte@Sun.COM 	    stmfIoctl.stmf_obuf_max_nentries * sizeof (stmfDevid) +
42867836SJohn.Forte@Sun.COM 	    sizeof (stmfDevidList));
42879585STim.Szeto@Sun.COM 	if (*targetList == NULL) {
42889585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
42899585STim.Szeto@Sun.COM 		goto done;
42909585STim.Szeto@Sun.COM 	}
42917836SJohn.Forte@Sun.COM 
42927836SJohn.Forte@Sun.COM 	(*targetList)->cnt = stmfIoctl.stmf_obuf_max_nentries;
42937836SJohn.Forte@Sun.COM 	for (i = 0; i < stmfIoctl.stmf_obuf_max_nentries; i++, fTargetList++) {
42947836SJohn.Forte@Sun.COM 		(*targetList)->devid[i].identLength =
42957836SJohn.Forte@Sun.COM 		    fTargetList->target[IDENT_LENGTH_BYTE];
42967836SJohn.Forte@Sun.COM 		bcopy(&fTargetList->target[IDENT_LENGTH_BYTE + 1],
42977836SJohn.Forte@Sun.COM 		    &(*targetList)->devid[i].ident,
42987836SJohn.Forte@Sun.COM 		    fTargetList->target[IDENT_LENGTH_BYTE]);
42997836SJohn.Forte@Sun.COM 	}
43007836SJohn.Forte@Sun.COM 
43017836SJohn.Forte@Sun.COM done:
43027836SJohn.Forte@Sun.COM 	(void) close(fd);
43038252SJohn.Forte@Sun.COM 	free(fTargetListP);
43047836SJohn.Forte@Sun.COM 	return (ret);
43057836SJohn.Forte@Sun.COM }
43067836SJohn.Forte@Sun.COM 
43077836SJohn.Forte@Sun.COM /*
43087836SJohn.Forte@Sun.COM  * stmfGetTargetProperties
43097836SJohn.Forte@Sun.COM  *
43107836SJohn.Forte@Sun.COM  * Purpose:  Retrieves the properties for a logical unit
43117836SJohn.Forte@Sun.COM  *
43127836SJohn.Forte@Sun.COM  * devid - devid of the target for which to retrieve properties
43137836SJohn.Forte@Sun.COM  * targetProps - pointer to an stmfTargetProperties structure.
43147836SJohn.Forte@Sun.COM  *		On success, it contains the target properties for
43157836SJohn.Forte@Sun.COM  *		the specified devid.
43167836SJohn.Forte@Sun.COM  */
43177836SJohn.Forte@Sun.COM int
43187836SJohn.Forte@Sun.COM stmfGetTargetProperties(stmfDevid *devid, stmfTargetProperties *targetProps)
43197836SJohn.Forte@Sun.COM {
43207836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
43217836SJohn.Forte@Sun.COM 	int fd;
43227836SJohn.Forte@Sun.COM 	int ioctlRet;
43237836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
43247836SJohn.Forte@Sun.COM 	sioc_target_port_props_t targetProperties;
432510725SJohn.Forte@Sun.COM 	scsi_devid_desc_t *scsiDevid;
43267836SJohn.Forte@Sun.COM 
43277836SJohn.Forte@Sun.COM 	if (devid == NULL || targetProps == NULL) {
43287836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
43297836SJohn.Forte@Sun.COM 	}
43307836SJohn.Forte@Sun.COM 
43317836SJohn.Forte@Sun.COM 	/* call init */
43327836SJohn.Forte@Sun.COM 	ret = initializeConfig();
43337836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
43347836SJohn.Forte@Sun.COM 		return (ret);
43357836SJohn.Forte@Sun.COM 	}
43367836SJohn.Forte@Sun.COM 
43377836SJohn.Forte@Sun.COM 	/*
43387836SJohn.Forte@Sun.COM 	 * Open control node for stmf
43397836SJohn.Forte@Sun.COM 	 */
43407836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
43417836SJohn.Forte@Sun.COM 		return (ret);
43427836SJohn.Forte@Sun.COM 
43437836SJohn.Forte@Sun.COM 	targetProperties.tgt_id[IDENT_LENGTH_BYTE] = devid->identLength;
43447836SJohn.Forte@Sun.COM 	bcopy(&(devid->ident), &targetProperties.tgt_id[IDENT_LENGTH_BYTE + 1],
43457836SJohn.Forte@Sun.COM 	    devid->identLength);
43467836SJohn.Forte@Sun.COM 
43477836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
43487836SJohn.Forte@Sun.COM 	/*
43497836SJohn.Forte@Sun.COM 	 * Issue ioctl to add to the host group
43507836SJohn.Forte@Sun.COM 	 */
43517836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
43527836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (targetProperties.tgt_id);
43537836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&targetProperties.tgt_id;
43547836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&targetProperties;
43557836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = sizeof (targetProperties);
43567836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_GET_TARGET_PORT_PROPERTIES,
43577836SJohn.Forte@Sun.COM 	    &stmfIoctl);
43587836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
43597836SJohn.Forte@Sun.COM 		switch (errno) {
43607836SJohn.Forte@Sun.COM 			case EBUSY:
43617836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
43627836SJohn.Forte@Sun.COM 				break;
43639585STim.Szeto@Sun.COM 			case EPERM:
43647836SJohn.Forte@Sun.COM 			case EACCES:
43657836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
43667836SJohn.Forte@Sun.COM 				break;
43677836SJohn.Forte@Sun.COM 			case ENOENT:
43687836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
43697836SJohn.Forte@Sun.COM 				break;
43707836SJohn.Forte@Sun.COM 			default:
43717836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
43727836SJohn.Forte@Sun.COM 				    "stmfGetTargetProperties:ioctl errno(%d)",
43737836SJohn.Forte@Sun.COM 				    errno);
43747836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
43757836SJohn.Forte@Sun.COM 				break;
43767836SJohn.Forte@Sun.COM 		}
43777836SJohn.Forte@Sun.COM 		goto done;
43787836SJohn.Forte@Sun.COM 	}
43797836SJohn.Forte@Sun.COM 
43807836SJohn.Forte@Sun.COM 	bcopy(targetProperties.tgt_provider_name, targetProps->providerName,
43817836SJohn.Forte@Sun.COM 	    sizeof (targetProperties.tgt_provider_name));
43827836SJohn.Forte@Sun.COM 	if (targetProperties.tgt_state == STMF_STATE_ONLINE) {
43837836SJohn.Forte@Sun.COM 		targetProps->status = STMF_TARGET_PORT_ONLINE;
43847836SJohn.Forte@Sun.COM 	} else if (targetProperties.tgt_state == STMF_STATE_OFFLINE) {
43857836SJohn.Forte@Sun.COM 		targetProps->status = STMF_TARGET_PORT_OFFLINE;
43867836SJohn.Forte@Sun.COM 	} else if (targetProperties.tgt_state == STMF_STATE_ONLINING) {
43877836SJohn.Forte@Sun.COM 		targetProps->status = STMF_TARGET_PORT_ONLINING;
43887836SJohn.Forte@Sun.COM 	} else if (targetProperties.tgt_state == STMF_STATE_OFFLINING) {
43897836SJohn.Forte@Sun.COM 		targetProps->status = STMF_TARGET_PORT_OFFLINING;
43907836SJohn.Forte@Sun.COM 	}
43917836SJohn.Forte@Sun.COM 	bcopy(targetProperties.tgt_alias, targetProps->alias,
43927836SJohn.Forte@Sun.COM 	    sizeof (targetProps->alias));
439310725SJohn.Forte@Sun.COM 
439410725SJohn.Forte@Sun.COM 	scsiDevid = (scsi_devid_desc_t *)&targetProperties.tgt_id;
439510725SJohn.Forte@Sun.COM 	targetProps->protocol = scsiDevid->protocol_id;
439610725SJohn.Forte@Sun.COM 
43977836SJohn.Forte@Sun.COM done:
43987836SJohn.Forte@Sun.COM 	(void) close(fd);
43997836SJohn.Forte@Sun.COM 	return (ret);
44007836SJohn.Forte@Sun.COM }
44017836SJohn.Forte@Sun.COM 
44027836SJohn.Forte@Sun.COM /*
44037836SJohn.Forte@Sun.COM  * stmfGetLogicalUnitList
44047836SJohn.Forte@Sun.COM  *
44057836SJohn.Forte@Sun.COM  * Purpose: Retrieves list of logical unit Object IDs
44067836SJohn.Forte@Sun.COM  *
44077836SJohn.Forte@Sun.COM  * luList - pointer to a pointer to a stmfGuidList structure. On success,
44087836SJohn.Forte@Sun.COM  *          it contains the list of logical unit guids.
44097836SJohn.Forte@Sun.COM  *
44107836SJohn.Forte@Sun.COM  */
44117836SJohn.Forte@Sun.COM int
44127836SJohn.Forte@Sun.COM stmfGetLogicalUnitList(stmfGuidList **luList)
44137836SJohn.Forte@Sun.COM {
44147836SJohn.Forte@Sun.COM 	int ret;
44157836SJohn.Forte@Sun.COM 	int fd;
44167836SJohn.Forte@Sun.COM 	int ioctlRet;
44177836SJohn.Forte@Sun.COM 	int cmd = STMF_IOCTL_LU_LIST;
44189585STim.Szeto@Sun.COM 	int i;
44197836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
44207836SJohn.Forte@Sun.COM 	slist_lu_t *fLuList;
44217836SJohn.Forte@Sun.COM 	uint32_t fLuListSize;
44229585STim.Szeto@Sun.COM 	uint32_t listCnt;
44237836SJohn.Forte@Sun.COM 
44247836SJohn.Forte@Sun.COM 	if (luList == NULL) {
44257836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
44267836SJohn.Forte@Sun.COM 	}
44277836SJohn.Forte@Sun.COM 
44287836SJohn.Forte@Sun.COM 	/* call init */
44297836SJohn.Forte@Sun.COM 	ret = initializeConfig();
44307836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
44317836SJohn.Forte@Sun.COM 		return (ret);
44327836SJohn.Forte@Sun.COM 	}
44337836SJohn.Forte@Sun.COM 
44347836SJohn.Forte@Sun.COM 	/*
44357836SJohn.Forte@Sun.COM 	 * Open control node for stmf
44367836SJohn.Forte@Sun.COM 	 */
44377836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
44387836SJohn.Forte@Sun.COM 		return (ret);
44397836SJohn.Forte@Sun.COM 
44407836SJohn.Forte@Sun.COM 	/*
44417836SJohn.Forte@Sun.COM 	 * Allocate ioctl input buffer
44427836SJohn.Forte@Sun.COM 	 */
44439585STim.Szeto@Sun.COM 	fLuListSize = ALLOC_LU;
44447836SJohn.Forte@Sun.COM 	fLuListSize = fLuListSize * (sizeof (slist_lu_t));
44457836SJohn.Forte@Sun.COM 	fLuList = (slist_lu_t *)calloc(1, fLuListSize);
44467836SJohn.Forte@Sun.COM 	if (fLuList == NULL) {
44479585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
44489585STim.Szeto@Sun.COM 		goto done;
44497836SJohn.Forte@Sun.COM 	}
44507836SJohn.Forte@Sun.COM 
44517836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
44527836SJohn.Forte@Sun.COM 	/*
44537836SJohn.Forte@Sun.COM 	 * Issue ioctl to get the LU list
44547836SJohn.Forte@Sun.COM 	 */
44557836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
44567836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = fLuListSize;
44577836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fLuList;
44587836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
44597836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
44607836SJohn.Forte@Sun.COM 		switch (errno) {
44617836SJohn.Forte@Sun.COM 			case EBUSY:
44627836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
44637836SJohn.Forte@Sun.COM 				break;
44649585STim.Szeto@Sun.COM 			case EPERM:
44657836SJohn.Forte@Sun.COM 			case EACCES:
44667836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
44677836SJohn.Forte@Sun.COM 				break;
44687836SJohn.Forte@Sun.COM 			default:
44697836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
44707836SJohn.Forte@Sun.COM 				    "stmfGetLogicalUnitList:ioctl errno(%d)",
44717836SJohn.Forte@Sun.COM 				    errno);
44727836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
44737836SJohn.Forte@Sun.COM 				break;
44747836SJohn.Forte@Sun.COM 		}
44757836SJohn.Forte@Sun.COM 		goto done;
44767836SJohn.Forte@Sun.COM 	}
44777836SJohn.Forte@Sun.COM 	/*
44787836SJohn.Forte@Sun.COM 	 * Check whether input buffer was large enough
44797836SJohn.Forte@Sun.COM 	 */
44809585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_LU) {
44817836SJohn.Forte@Sun.COM 		fLuListSize = stmfIoctl.stmf_obuf_max_nentries *
44827836SJohn.Forte@Sun.COM 		    sizeof (slist_lu_t);
44839585STim.Szeto@Sun.COM 		free(fLuList);
44849585STim.Szeto@Sun.COM 		fLuList = (slist_lu_t *)calloc(1, fLuListSize);
44857836SJohn.Forte@Sun.COM 		if (fLuList == NULL) {
44869585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NOMEM;
44879585STim.Szeto@Sun.COM 			goto done;
44887836SJohn.Forte@Sun.COM 		}
44897836SJohn.Forte@Sun.COM 		stmfIoctl.stmf_obuf_size = fLuListSize;
44907836SJohn.Forte@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fLuList;
44917836SJohn.Forte@Sun.COM 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
44927836SJohn.Forte@Sun.COM 		if (ioctlRet != 0) {
44937836SJohn.Forte@Sun.COM 			switch (errno) {
44947836SJohn.Forte@Sun.COM 				case EBUSY:
44957836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_BUSY;
44967836SJohn.Forte@Sun.COM 					break;
44979585STim.Szeto@Sun.COM 				case EPERM:
44987836SJohn.Forte@Sun.COM 				case EACCES:
44997836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_PERM;
45007836SJohn.Forte@Sun.COM 					break;
45017836SJohn.Forte@Sun.COM 				default:
45027836SJohn.Forte@Sun.COM 					syslog(LOG_DEBUG,
45037836SJohn.Forte@Sun.COM 					    "stmfGetLogicalUnitList:"
45047836SJohn.Forte@Sun.COM 					    "ioctl errno(%d)", errno);
45057836SJohn.Forte@Sun.COM 					ret = STMF_STATUS_ERROR;
45067836SJohn.Forte@Sun.COM 					break;
45077836SJohn.Forte@Sun.COM 			}
45087836SJohn.Forte@Sun.COM 			goto done;
45097836SJohn.Forte@Sun.COM 		}
45107836SJohn.Forte@Sun.COM 	}
45117836SJohn.Forte@Sun.COM 
45127836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
45137836SJohn.Forte@Sun.COM 		goto done;
45147836SJohn.Forte@Sun.COM 	}
45157836SJohn.Forte@Sun.COM 
45169585STim.Szeto@Sun.COM 	listCnt = stmfIoctl.stmf_obuf_nentries;
45177836SJohn.Forte@Sun.COM 
45187836SJohn.Forte@Sun.COM 	/*
45197836SJohn.Forte@Sun.COM 	 * allocate caller's buffer with the final size
45207836SJohn.Forte@Sun.COM 	 */
45217836SJohn.Forte@Sun.COM 	*luList = (stmfGuidList *)calloc(1, sizeof (stmfGuidList) +
45229585STim.Szeto@Sun.COM 	    listCnt * sizeof (stmfGuid));
45237836SJohn.Forte@Sun.COM 	if (*luList == NULL) {
45247836SJohn.Forte@Sun.COM 		ret = STMF_ERROR_NOMEM;
45257836SJohn.Forte@Sun.COM 		goto done;
45267836SJohn.Forte@Sun.COM 	}
45277836SJohn.Forte@Sun.COM 
45289585STim.Szeto@Sun.COM 	(*luList)->cnt = listCnt;
45299585STim.Szeto@Sun.COM 
45309585STim.Szeto@Sun.COM 	/* copy to caller's buffer */
45319585STim.Szeto@Sun.COM 	for (i = 0; i < listCnt; i++) {
45329585STim.Szeto@Sun.COM 		bcopy(&fLuList[i].lu_guid, (*luList)->guid[i].guid,
45339585STim.Szeto@Sun.COM 		    sizeof (stmfGuid));
45349585STim.Szeto@Sun.COM 	}
45359585STim.Szeto@Sun.COM 
45367836SJohn.Forte@Sun.COM 	/*
45379585STim.Szeto@Sun.COM 	 * sort the list. This gives a consistent view across gets
45387836SJohn.Forte@Sun.COM 	 */
45399585STim.Szeto@Sun.COM 	qsort((void *)&((*luList)->guid[0]), (*luList)->cnt,
45409585STim.Szeto@Sun.COM 	    sizeof (stmfGuid), guidCompare);
45417836SJohn.Forte@Sun.COM 
45427836SJohn.Forte@Sun.COM done:
45437836SJohn.Forte@Sun.COM 	(void) close(fd);
45447836SJohn.Forte@Sun.COM 	/*
45457836SJohn.Forte@Sun.COM 	 * free internal buffers
45467836SJohn.Forte@Sun.COM 	 */
45477836SJohn.Forte@Sun.COM 	free(fLuList);
45487836SJohn.Forte@Sun.COM 	return (ret);
45497836SJohn.Forte@Sun.COM }
45507836SJohn.Forte@Sun.COM 
45517836SJohn.Forte@Sun.COM /*
45527836SJohn.Forte@Sun.COM  * stmfGetLogicalUnitProperties
45537836SJohn.Forte@Sun.COM  *
45547836SJohn.Forte@Sun.COM  * Purpose:  Retrieves the properties for a logical unit
45557836SJohn.Forte@Sun.COM  *
45567836SJohn.Forte@Sun.COM  * lu - guid of the logical unit for which to retrieve properties
45577836SJohn.Forte@Sun.COM  * stmfLuProps - pointer to an stmfLogicalUnitProperties structure. On success,
45587836SJohn.Forte@Sun.COM  *               it contains the logical unit properties for the specified guid.
45597836SJohn.Forte@Sun.COM  */
45607836SJohn.Forte@Sun.COM int
45617836SJohn.Forte@Sun.COM stmfGetLogicalUnitProperties(stmfGuid *lu, stmfLogicalUnitProperties *luProps)
45627836SJohn.Forte@Sun.COM {
45637836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
45647836SJohn.Forte@Sun.COM 	int stmfRet;
45657836SJohn.Forte@Sun.COM 	int fd;
45667836SJohn.Forte@Sun.COM 	int ioctlRet;
45677836SJohn.Forte@Sun.COM 	int cmd = STMF_IOCTL_GET_LU_PROPERTIES;
45687836SJohn.Forte@Sun.COM 	stmfViewEntryList *viewEntryList = NULL;
45697836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
45707836SJohn.Forte@Sun.COM 	sioc_lu_props_t fLuProps;
45717836SJohn.Forte@Sun.COM 
45729585STim.Szeto@Sun.COM 	if (lu == NULL || luProps == NULL) {
45739585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
45747836SJohn.Forte@Sun.COM 	}
45757836SJohn.Forte@Sun.COM 
45767836SJohn.Forte@Sun.COM 	bzero(luProps, sizeof (stmfLogicalUnitProperties));
45777836SJohn.Forte@Sun.COM 
45787836SJohn.Forte@Sun.COM 	/* call init */
45797836SJohn.Forte@Sun.COM 	ret = initializeConfig();
45807836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
45817836SJohn.Forte@Sun.COM 		return (ret);
45827836SJohn.Forte@Sun.COM 	}
45837836SJohn.Forte@Sun.COM 
45847836SJohn.Forte@Sun.COM 	/*
45857836SJohn.Forte@Sun.COM 	 * Open control node for stmf
45867836SJohn.Forte@Sun.COM 	 */
45877836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
45887836SJohn.Forte@Sun.COM 		return (ret);
45897836SJohn.Forte@Sun.COM 
45907836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
45917836SJohn.Forte@Sun.COM 	/*
45927836SJohn.Forte@Sun.COM 	 * Issue ioctl to add to the host group
45937836SJohn.Forte@Sun.COM 	 */
45947836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
45957836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (stmfGuid);
45967836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)lu;
45977836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&fLuProps;
45987836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = sizeof (fLuProps);
45997836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
46007836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
46017836SJohn.Forte@Sun.COM 		switch (errno) {
46027836SJohn.Forte@Sun.COM 			case EBUSY:
46037836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
46047836SJohn.Forte@Sun.COM 				break;
46059585STim.Szeto@Sun.COM 			case EPERM:
46067836SJohn.Forte@Sun.COM 			case EACCES:
46077836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
46087836SJohn.Forte@Sun.COM 				break;
46097836SJohn.Forte@Sun.COM 			case ENOENT:
46107836SJohn.Forte@Sun.COM 				stmfRet = stmfGetViewEntryList(lu,
46117836SJohn.Forte@Sun.COM 				    &viewEntryList);
46127836SJohn.Forte@Sun.COM 				if (stmfRet == STMF_STATUS_SUCCESS) {
46137836SJohn.Forte@Sun.COM 					luProps->status =
46147836SJohn.Forte@Sun.COM 					    STMF_LOGICAL_UNIT_UNREGISTERED;
46157836SJohn.Forte@Sun.COM 					if (viewEntryList->cnt > 0) {
46167836SJohn.Forte@Sun.COM 						ret = STMF_STATUS_SUCCESS;
46177836SJohn.Forte@Sun.COM 					} else {
46187836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_NOT_FOUND;
46197836SJohn.Forte@Sun.COM 					}
46207836SJohn.Forte@Sun.COM 				} else {
46217836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_NOT_FOUND;
46227836SJohn.Forte@Sun.COM 				}
46237836SJohn.Forte@Sun.COM 				stmfFreeMemory(viewEntryList);
46247836SJohn.Forte@Sun.COM 				break;
46257836SJohn.Forte@Sun.COM 			default:
46267836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
46277836SJohn.Forte@Sun.COM 				    "stmfGetLogicalUnit:ioctl errno(%d)",
46287836SJohn.Forte@Sun.COM 				    errno);
46297836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
46307836SJohn.Forte@Sun.COM 				break;
46317836SJohn.Forte@Sun.COM 		}
46327836SJohn.Forte@Sun.COM 		goto done;
46337836SJohn.Forte@Sun.COM 	}
46347836SJohn.Forte@Sun.COM 
46357836SJohn.Forte@Sun.COM 	bcopy(fLuProps.lu_provider_name, luProps->providerName,
46367836SJohn.Forte@Sun.COM 	    sizeof (fLuProps.lu_provider_name));
46377836SJohn.Forte@Sun.COM 	if (fLuProps.lu_state == STMF_STATE_ONLINE) {
46387836SJohn.Forte@Sun.COM 		luProps->status = STMF_LOGICAL_UNIT_ONLINE;
46397836SJohn.Forte@Sun.COM 	} else if (fLuProps.lu_state == STMF_STATE_OFFLINE) {
46407836SJohn.Forte@Sun.COM 		luProps->status = STMF_LOGICAL_UNIT_OFFLINE;
46417836SJohn.Forte@Sun.COM 	} else if (fLuProps.lu_state == STMF_STATE_ONLINING) {
46427836SJohn.Forte@Sun.COM 		luProps->status = STMF_LOGICAL_UNIT_ONLINING;
46437836SJohn.Forte@Sun.COM 	} else if (fLuProps.lu_state == STMF_STATE_OFFLINING) {
46447836SJohn.Forte@Sun.COM 		luProps->status = STMF_LOGICAL_UNIT_OFFLINING;
46457836SJohn.Forte@Sun.COM 	}
46467836SJohn.Forte@Sun.COM 	bcopy(fLuProps.lu_alias, luProps->alias, sizeof (luProps->alias));
46477836SJohn.Forte@Sun.COM done:
46487836SJohn.Forte@Sun.COM 	(void) close(fd);
46497836SJohn.Forte@Sun.COM 	return (ret);
46507836SJohn.Forte@Sun.COM }
46517836SJohn.Forte@Sun.COM 
46527836SJohn.Forte@Sun.COM /*
46537836SJohn.Forte@Sun.COM  * stmfGetState
46547836SJohn.Forte@Sun.COM  *
46557836SJohn.Forte@Sun.COM  * Purpose: retrieve the current state of the stmf module
46567836SJohn.Forte@Sun.COM  *
46577836SJohn.Forte@Sun.COM  * state - pointer to stmfState structure allocated by the caller
46587836SJohn.Forte@Sun.COM  *         On success, contains the state of stmf
46597836SJohn.Forte@Sun.COM  */
46607836SJohn.Forte@Sun.COM int
46617836SJohn.Forte@Sun.COM stmfGetState(stmfState *state)
46627836SJohn.Forte@Sun.COM {
46637836SJohn.Forte@Sun.COM 	int ret;
46647836SJohn.Forte@Sun.COM 	stmf_state_desc_t iState;
46657836SJohn.Forte@Sun.COM 
46667836SJohn.Forte@Sun.COM 	if (state == NULL) {
46677836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
46687836SJohn.Forte@Sun.COM 	}
46697836SJohn.Forte@Sun.COM 
46707836SJohn.Forte@Sun.COM 	ret = getStmfState(&iState);
46717836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
46727836SJohn.Forte@Sun.COM 		return (ret);
46737836SJohn.Forte@Sun.COM 	}
46747836SJohn.Forte@Sun.COM 	switch (iState.state) {
46757836SJohn.Forte@Sun.COM 		case STMF_STATE_ONLINE:
46767836SJohn.Forte@Sun.COM 			state->operationalState =
46777836SJohn.Forte@Sun.COM 			    STMF_SERVICE_STATE_ONLINE;
46787836SJohn.Forte@Sun.COM 			break;
46797836SJohn.Forte@Sun.COM 		case STMF_STATE_OFFLINE:
46807836SJohn.Forte@Sun.COM 			state->operationalState =
46817836SJohn.Forte@Sun.COM 			    STMF_SERVICE_STATE_OFFLINE;
46827836SJohn.Forte@Sun.COM 			break;
46837836SJohn.Forte@Sun.COM 		case STMF_STATE_ONLINING:
46847836SJohn.Forte@Sun.COM 			state->operationalState =
46857836SJohn.Forte@Sun.COM 			    STMF_SERVICE_STATE_ONLINING;
46867836SJohn.Forte@Sun.COM 			break;
46877836SJohn.Forte@Sun.COM 		case STMF_STATE_OFFLINING:
46887836SJohn.Forte@Sun.COM 			state->operationalState =
46897836SJohn.Forte@Sun.COM 			    STMF_SERVICE_STATE_OFFLINING;
46907836SJohn.Forte@Sun.COM 			break;
46917836SJohn.Forte@Sun.COM 		default:
46927836SJohn.Forte@Sun.COM 			state->operationalState =
46937836SJohn.Forte@Sun.COM 			    STMF_SERVICE_STATE_UNKNOWN;
46947836SJohn.Forte@Sun.COM 			break;
46957836SJohn.Forte@Sun.COM 	}
46967836SJohn.Forte@Sun.COM 	switch (iState.config_state) {
46977836SJohn.Forte@Sun.COM 		case STMF_CONFIG_NONE:
46987836SJohn.Forte@Sun.COM 			state->configState = STMF_CONFIG_STATE_NONE;
46997836SJohn.Forte@Sun.COM 			break;
47007836SJohn.Forte@Sun.COM 		case STMF_CONFIG_INIT:
47017836SJohn.Forte@Sun.COM 			state->configState = STMF_CONFIG_STATE_INIT;
47027836SJohn.Forte@Sun.COM 			break;
47037836SJohn.Forte@Sun.COM 		case STMF_CONFIG_INIT_DONE:
47047836SJohn.Forte@Sun.COM 			state->configState =
47057836SJohn.Forte@Sun.COM 			    STMF_CONFIG_STATE_INIT_DONE;
47067836SJohn.Forte@Sun.COM 			break;
47077836SJohn.Forte@Sun.COM 		default:
47087836SJohn.Forte@Sun.COM 			state->configState =
47097836SJohn.Forte@Sun.COM 			    STMF_CONFIG_STATE_UNKNOWN;
47107836SJohn.Forte@Sun.COM 			break;
47117836SJohn.Forte@Sun.COM 	}
47127836SJohn.Forte@Sun.COM 	return (STMF_STATUS_SUCCESS);
47137836SJohn.Forte@Sun.COM }
47147836SJohn.Forte@Sun.COM 
47157836SJohn.Forte@Sun.COM /*
47167836SJohn.Forte@Sun.COM  * stmfGetViewEntryList
47177836SJohn.Forte@Sun.COM  *
47187836SJohn.Forte@Sun.COM  * Purpose: Retrieves the list of view entries for the specified
47197836SJohn.Forte@Sun.COM  *          logical unit.
47207836SJohn.Forte@Sun.COM  *
47217836SJohn.Forte@Sun.COM  * lu - the guid of the logical unit for which to retrieve the view entry list
47227836SJohn.Forte@Sun.COM  * viewEntryList - a pointer to a pointer to a stmfViewEntryList structure. On
47237836SJohn.Forte@Sun.COM  *                 success, contains the list of view entries.
47247836SJohn.Forte@Sun.COM  */
47257836SJohn.Forte@Sun.COM int
47267836SJohn.Forte@Sun.COM stmfGetViewEntryList(stmfGuid *lu, stmfViewEntryList **viewEntryList)
47277836SJohn.Forte@Sun.COM {
47287836SJohn.Forte@Sun.COM 	int ret;
47299585STim.Szeto@Sun.COM 	int fd;
47309585STim.Szeto@Sun.COM 	int ioctlRet;
47319585STim.Szeto@Sun.COM 	int cmd = STMF_IOCTL_LU_VE_LIST;
47329585STim.Szeto@Sun.COM 	int i;
47339585STim.Szeto@Sun.COM 	stmf_iocdata_t stmfIoctl;
47349585STim.Szeto@Sun.COM 	stmf_view_op_entry_t *fVeList;
47359585STim.Szeto@Sun.COM 	uint32_t fVeListSize;
47369585STim.Szeto@Sun.COM 	uint32_t listCnt;
47377836SJohn.Forte@Sun.COM 
47387836SJohn.Forte@Sun.COM 	if (lu == NULL || viewEntryList == NULL) {
47397836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
47407836SJohn.Forte@Sun.COM 	}
47417836SJohn.Forte@Sun.COM 
47429585STim.Szeto@Sun.COM 	/* call init */
47439585STim.Szeto@Sun.COM 	ret = initializeConfig();
47449585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
47459585STim.Szeto@Sun.COM 		return (ret);
47469585STim.Szeto@Sun.COM 	}
47479585STim.Szeto@Sun.COM 
47489585STim.Szeto@Sun.COM 	/*
47499585STim.Szeto@Sun.COM 	 * Open control node for stmf
47509585STim.Szeto@Sun.COM 	 */
47519585STim.Szeto@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
47529585STim.Szeto@Sun.COM 		return (ret);
47539585STim.Szeto@Sun.COM 
47549585STim.Szeto@Sun.COM 	/*
47559585STim.Szeto@Sun.COM 	 * Allocate ioctl input buffer
47569585STim.Szeto@Sun.COM 	 */
47579585STim.Szeto@Sun.COM 	fVeListSize = ALLOC_VE;
47589585STim.Szeto@Sun.COM 	fVeListSize = fVeListSize * (sizeof (stmf_view_op_entry_t));
47599585STim.Szeto@Sun.COM 	fVeList = (stmf_view_op_entry_t *)calloc(1, fVeListSize);
47609585STim.Szeto@Sun.COM 	if (fVeList == NULL) {
47619585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
47629585STim.Szeto@Sun.COM 		goto done;
47639585STim.Szeto@Sun.COM 	}
47649585STim.Szeto@Sun.COM 
47659585STim.Szeto@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
47669585STim.Szeto@Sun.COM 	/*
47679585STim.Szeto@Sun.COM 	 * Issue ioctl to get the LU list
47689585STim.Szeto@Sun.COM 	 */
47699585STim.Szeto@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
47709585STim.Szeto@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)lu;
47719585STim.Szeto@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (stmfGuid);
47729585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf_size = fVeListSize;
47739585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fVeList;
47749585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
47759585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
47769585STim.Szeto@Sun.COM 		switch (errno) {
47779585STim.Szeto@Sun.COM 			case EBUSY:
47789585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
47799585STim.Szeto@Sun.COM 				break;
47809585STim.Szeto@Sun.COM 			case EPERM:
47819585STim.Szeto@Sun.COM 			case EACCES:
47829585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
47839585STim.Szeto@Sun.COM 				break;
47849585STim.Szeto@Sun.COM 			default:
47859585STim.Szeto@Sun.COM 				syslog(LOG_DEBUG,
47869585STim.Szeto@Sun.COM 				    "stmfGetViewEntryList:ioctl errno(%d)",
47879585STim.Szeto@Sun.COM 				    errno);
47889585STim.Szeto@Sun.COM 				ret = STMF_STATUS_ERROR;
47899585STim.Szeto@Sun.COM 				break;
47909585STim.Szeto@Sun.COM 		}
47919585STim.Szeto@Sun.COM 		goto done;
47929585STim.Szeto@Sun.COM 	}
47939585STim.Szeto@Sun.COM 	/*
47949585STim.Szeto@Sun.COM 	 * Check whether input buffer was large enough
47959585STim.Szeto@Sun.COM 	 */
47969585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_VE) {
47979585STim.Szeto@Sun.COM 		bzero(&stmfIoctl, sizeof (stmfIoctl));
47989585STim.Szeto@Sun.COM 		fVeListSize = stmfIoctl.stmf_obuf_max_nentries *
47999585STim.Szeto@Sun.COM 		    sizeof (stmf_view_op_entry_t);
48009585STim.Szeto@Sun.COM 		free(fVeList);
48019585STim.Szeto@Sun.COM 		fVeList = (stmf_view_op_entry_t *)calloc(1, fVeListSize);
48029585STim.Szeto@Sun.COM 		if (fVeList == NULL) {
48039585STim.Szeto@Sun.COM 			return (STMF_ERROR_NOMEM);
48049585STim.Szeto@Sun.COM 		}
48059585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf_size = fVeListSize;
48069585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fVeList;
48079585STim.Szeto@Sun.COM 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
48089585STim.Szeto@Sun.COM 		if (ioctlRet != 0) {
48099585STim.Szeto@Sun.COM 			switch (errno) {
48109585STim.Szeto@Sun.COM 				case EBUSY:
48119585STim.Szeto@Sun.COM 					ret = STMF_ERROR_BUSY;
48129585STim.Szeto@Sun.COM 					break;
48139585STim.Szeto@Sun.COM 				case EPERM:
48149585STim.Szeto@Sun.COM 				case EACCES:
48159585STim.Szeto@Sun.COM 					ret = STMF_ERROR_PERM;
48169585STim.Szeto@Sun.COM 					break;
48179585STim.Szeto@Sun.COM 				default:
48189585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
48199585STim.Szeto@Sun.COM 					    "stmfGetLogicalUnitList:"
48209585STim.Szeto@Sun.COM 					    "ioctl errno(%d)", errno);
48219585STim.Szeto@Sun.COM 					ret = STMF_STATUS_ERROR;
48229585STim.Szeto@Sun.COM 					break;
48239585STim.Szeto@Sun.COM 			}
48249585STim.Szeto@Sun.COM 			goto done;
48259585STim.Szeto@Sun.COM 		}
48269585STim.Szeto@Sun.COM 	}
48279585STim.Szeto@Sun.COM 
48289585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
48299585STim.Szeto@Sun.COM 		goto done;
48309585STim.Szeto@Sun.COM 	}
48319585STim.Szeto@Sun.COM 
48329585STim.Szeto@Sun.COM 	listCnt = stmfIoctl.stmf_obuf_nentries;
48339585STim.Szeto@Sun.COM 
48349585STim.Szeto@Sun.COM 	/*
48359585STim.Szeto@Sun.COM 	 * allocate caller's buffer with the final size
48369585STim.Szeto@Sun.COM 	 */
48379585STim.Szeto@Sun.COM 	*viewEntryList = (stmfViewEntryList *)calloc(1,
48389585STim.Szeto@Sun.COM 	    sizeof (stmfViewEntryList) + listCnt * sizeof (stmfViewEntry));
48399585STim.Szeto@Sun.COM 	if (*viewEntryList == NULL) {
48409585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
48419585STim.Szeto@Sun.COM 		goto done;
48429585STim.Szeto@Sun.COM 	}
48439585STim.Szeto@Sun.COM 
48449585STim.Szeto@Sun.COM 	(*viewEntryList)->cnt = listCnt;
48459585STim.Szeto@Sun.COM 
48469585STim.Szeto@Sun.COM 	/* copy to caller's buffer */
48479585STim.Szeto@Sun.COM 	for (i = 0; i < listCnt; i++) {
48489585STim.Szeto@Sun.COM 		(*viewEntryList)->ve[i].veIndexValid = B_TRUE;
48499585STim.Szeto@Sun.COM 		(*viewEntryList)->ve[i].veIndex = fVeList[i].ve_ndx;
48509585STim.Szeto@Sun.COM 		if (fVeList[i].ve_all_hosts == 1) {
48519585STim.Szeto@Sun.COM 			(*viewEntryList)->ve[i].allHosts = B_TRUE;
48529585STim.Szeto@Sun.COM 		} else {
48539585STim.Szeto@Sun.COM 			bcopy(fVeList[i].ve_host_group.name,
48549585STim.Szeto@Sun.COM 			    (*viewEntryList)->ve[i].hostGroup,
48559585STim.Szeto@Sun.COM 			    fVeList[i].ve_host_group.name_size);
48569585STim.Szeto@Sun.COM 		}
48579585STim.Szeto@Sun.COM 		if (fVeList[i].ve_all_targets == 1) {
48589585STim.Szeto@Sun.COM 			(*viewEntryList)->ve[i].allTargets = B_TRUE;
48599585STim.Szeto@Sun.COM 		} else {
48609585STim.Szeto@Sun.COM 			bcopy(fVeList[i].ve_target_group.name,
48619585STim.Szeto@Sun.COM 			    (*viewEntryList)->ve[i].targetGroup,
48629585STim.Szeto@Sun.COM 			    fVeList[i].ve_target_group.name_size);
48639585STim.Szeto@Sun.COM 		}
48649585STim.Szeto@Sun.COM 		bcopy(fVeList[i].ve_lu_nbr, (*viewEntryList)->ve[i].luNbr,
48659585STim.Szeto@Sun.COM 		    sizeof ((*viewEntryList)->ve[i].luNbr));
48669585STim.Szeto@Sun.COM 		(*viewEntryList)->ve[i].luNbrValid = B_TRUE;
48679585STim.Szeto@Sun.COM 	}
48689585STim.Szeto@Sun.COM 
48699585STim.Szeto@Sun.COM 	/*
48709585STim.Szeto@Sun.COM 	 * sort the list. This gives a consistent view across gets
48719585STim.Szeto@Sun.COM 	 */
48729585STim.Szeto@Sun.COM 	qsort((void *)&((*viewEntryList)->ve[0]), (*viewEntryList)->cnt,
48739585STim.Szeto@Sun.COM 	    sizeof (stmfViewEntry), viewEntryCompare);
48749585STim.Szeto@Sun.COM 
48759585STim.Szeto@Sun.COM done:
48769585STim.Szeto@Sun.COM 	(void) close(fd);
48779585STim.Szeto@Sun.COM 	/*
48789585STim.Szeto@Sun.COM 	 * free internal buffers
48799585STim.Szeto@Sun.COM 	 */
48809585STim.Szeto@Sun.COM 	free(fVeList);
48817836SJohn.Forte@Sun.COM 	return (ret);
48827836SJohn.Forte@Sun.COM }
48837836SJohn.Forte@Sun.COM 
48849585STim.Szeto@Sun.COM 
48857836SJohn.Forte@Sun.COM /*
48867836SJohn.Forte@Sun.COM  * loadHostGroups
48877836SJohn.Forte@Sun.COM  *
48887836SJohn.Forte@Sun.COM  * Purpose - issues the ioctl to load the host groups into stmf
48897836SJohn.Forte@Sun.COM  *
48907836SJohn.Forte@Sun.COM  * fd - file descriptor for the control node of stmf.
48917836SJohn.Forte@Sun.COM  * groupList - populated host group list
48927836SJohn.Forte@Sun.COM  */
48937836SJohn.Forte@Sun.COM static int
48947836SJohn.Forte@Sun.COM loadHostGroups(int fd, stmfGroupList *groupList)
48957836SJohn.Forte@Sun.COM {
48967836SJohn.Forte@Sun.COM 	int i, j;
48977836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
48987836SJohn.Forte@Sun.COM 	stmfGroupProperties *groupProps = NULL;
48997836SJohn.Forte@Sun.COM 
49007836SJohn.Forte@Sun.COM 	for (i = 0; i < groupList->cnt; i++) {
49017836SJohn.Forte@Sun.COM 		if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_HOST_GROUP,
49027836SJohn.Forte@Sun.COM 		    &(groupList->name[i]))) != STMF_STATUS_SUCCESS) {
49037836SJohn.Forte@Sun.COM 			goto out;
49047836SJohn.Forte@Sun.COM 		}
49059585STim.Szeto@Sun.COM 		ret = iLoadGroupMembersFromPs(&(groupList->name[i]),
49069585STim.Szeto@Sun.COM 		    &groupProps, HOST_GROUP);
49077836SJohn.Forte@Sun.COM 		for (j = 0; j < groupProps->cnt; j++) {
49087836SJohn.Forte@Sun.COM 			if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_HG_ENTRY,
49097836SJohn.Forte@Sun.COM 			    &(groupList->name[i]), &(groupProps->name[j])))
49107836SJohn.Forte@Sun.COM 			    != STMF_STATUS_SUCCESS) {
49117836SJohn.Forte@Sun.COM 				goto out;
49127836SJohn.Forte@Sun.COM 			}
49137836SJohn.Forte@Sun.COM 		}
49147836SJohn.Forte@Sun.COM 	}
49157836SJohn.Forte@Sun.COM 
49167836SJohn.Forte@Sun.COM 
49177836SJohn.Forte@Sun.COM out:
49187836SJohn.Forte@Sun.COM 	stmfFreeMemory(groupProps);
49197836SJohn.Forte@Sun.COM 	return (ret);
49207836SJohn.Forte@Sun.COM }
49217836SJohn.Forte@Sun.COM 
49227836SJohn.Forte@Sun.COM /*
49237836SJohn.Forte@Sun.COM  * loadTargetGroups
49247836SJohn.Forte@Sun.COM  *
49257836SJohn.Forte@Sun.COM  * Purpose - issues the ioctl to load the target groups into stmf
49267836SJohn.Forte@Sun.COM  *
49277836SJohn.Forte@Sun.COM  * fd - file descriptor for the control node of stmf.
49287836SJohn.Forte@Sun.COM  * groupList - populated target group list.
49297836SJohn.Forte@Sun.COM  */
49307836SJohn.Forte@Sun.COM static int
49317836SJohn.Forte@Sun.COM loadTargetGroups(int fd, stmfGroupList *groupList)
49327836SJohn.Forte@Sun.COM {
49337836SJohn.Forte@Sun.COM 	int i, j;
49347836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
49357836SJohn.Forte@Sun.COM 	stmfGroupProperties *groupProps = NULL;
49367836SJohn.Forte@Sun.COM 
49377836SJohn.Forte@Sun.COM 	for (i = 0; i < groupList->cnt; i++) {
49387836SJohn.Forte@Sun.COM 		if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_TARGET_GROUP,
49397836SJohn.Forte@Sun.COM 		    &(groupList->name[i]))) != STMF_STATUS_SUCCESS) {
49407836SJohn.Forte@Sun.COM 			goto out;
49417836SJohn.Forte@Sun.COM 		}
49429585STim.Szeto@Sun.COM 		ret = iLoadGroupMembersFromPs(&(groupList->name[i]),
49439585STim.Szeto@Sun.COM 		    &groupProps, TARGET_GROUP);
49447836SJohn.Forte@Sun.COM 		for (j = 0; j < groupProps->cnt; j++) {
49457836SJohn.Forte@Sun.COM 			if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_TG_ENTRY,
49467836SJohn.Forte@Sun.COM 			    &(groupList->name[i]), &(groupProps->name[j])))
49477836SJohn.Forte@Sun.COM 			    != STMF_STATUS_SUCCESS) {
49487836SJohn.Forte@Sun.COM 				goto out;
49497836SJohn.Forte@Sun.COM 			}
49507836SJohn.Forte@Sun.COM 		}
49517836SJohn.Forte@Sun.COM 	}
49527836SJohn.Forte@Sun.COM 
49537836SJohn.Forte@Sun.COM 
49547836SJohn.Forte@Sun.COM out:
49557836SJohn.Forte@Sun.COM 	stmfFreeMemory(groupProps);
49567836SJohn.Forte@Sun.COM 	return (ret);
49577836SJohn.Forte@Sun.COM }
49587836SJohn.Forte@Sun.COM 
49597836SJohn.Forte@Sun.COM 
49607836SJohn.Forte@Sun.COM /*
49617836SJohn.Forte@Sun.COM  * loadStore
49627836SJohn.Forte@Sun.COM  *
49637836SJohn.Forte@Sun.COM  * Purpose: Load the configuration data from the store
49647836SJohn.Forte@Sun.COM  *
49657836SJohn.Forte@Sun.COM  * First load the host groups and target groups, then the view entries
49667836SJohn.Forte@Sun.COM  * and finally the provider data
49677836SJohn.Forte@Sun.COM  *
49687836SJohn.Forte@Sun.COM  * fd - file descriptor of control node for stmf.
49697836SJohn.Forte@Sun.COM  */
49707836SJohn.Forte@Sun.COM static int
49717836SJohn.Forte@Sun.COM loadStore(int fd)
49727836SJohn.Forte@Sun.COM {
49737836SJohn.Forte@Sun.COM 	int ret;
49747836SJohn.Forte@Sun.COM 	int i, j;
49757836SJohn.Forte@Sun.COM 	stmfGroupList *groupList = NULL;
49767836SJohn.Forte@Sun.COM 	stmfGuidList *guidList = NULL;
49777836SJohn.Forte@Sun.COM 	stmfViewEntryList *viewEntryList = NULL;
49787836SJohn.Forte@Sun.COM 	stmfProviderList *providerList = NULL;
49797836SJohn.Forte@Sun.COM 	int providerType;
49807836SJohn.Forte@Sun.COM 	nvlist_t *nvl = NULL;
49817836SJohn.Forte@Sun.COM 
49827836SJohn.Forte@Sun.COM 
49837836SJohn.Forte@Sun.COM 
49847836SJohn.Forte@Sun.COM 	/* load host groups */
49859585STim.Szeto@Sun.COM 	ret = iLoadGroupFromPs(&groupList, HOST_GROUP);
49867836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
49877836SJohn.Forte@Sun.COM 		return (ret);
49887836SJohn.Forte@Sun.COM 	}
49897836SJohn.Forte@Sun.COM 	ret = loadHostGroups(fd, groupList);
49907836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
49917836SJohn.Forte@Sun.COM 		goto out;
49927836SJohn.Forte@Sun.COM 	}
49937836SJohn.Forte@Sun.COM 
49947836SJohn.Forte@Sun.COM 	stmfFreeMemory(groupList);
49957836SJohn.Forte@Sun.COM 	groupList = NULL;
49967836SJohn.Forte@Sun.COM 
49977836SJohn.Forte@Sun.COM 	/* load target groups */
49989585STim.Szeto@Sun.COM 	ret = iLoadGroupFromPs(&groupList, TARGET_GROUP);
49997836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
50007836SJohn.Forte@Sun.COM 		goto out;
50017836SJohn.Forte@Sun.COM 	}
50027836SJohn.Forte@Sun.COM 	ret = loadTargetGroups(fd, groupList);
50037836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
50047836SJohn.Forte@Sun.COM 		goto out;
50057836SJohn.Forte@Sun.COM 	}
50067836SJohn.Forte@Sun.COM 
50077836SJohn.Forte@Sun.COM 	stmfFreeMemory(groupList);
50087836SJohn.Forte@Sun.COM 	groupList = NULL;
50097836SJohn.Forte@Sun.COM 
50107836SJohn.Forte@Sun.COM 	/* Get the guid list */
50117836SJohn.Forte@Sun.COM 	ret = psGetLogicalUnitList(&guidList);
50127836SJohn.Forte@Sun.COM 	switch (ret) {
50137836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
50147836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
50157836SJohn.Forte@Sun.COM 			break;
50167836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
50177836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
50187836SJohn.Forte@Sun.COM 			break;
50197836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
50207836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
50217836SJohn.Forte@Sun.COM 			break;
50227836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
50237836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
50247836SJohn.Forte@Sun.COM 			break;
50257836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
50267836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
50277836SJohn.Forte@Sun.COM 			break;
50287836SJohn.Forte@Sun.COM 		default:
50297836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
50307836SJohn.Forte@Sun.COM 			break;
50317836SJohn.Forte@Sun.COM 	}
50327836SJohn.Forte@Sun.COM 
50337836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
50347836SJohn.Forte@Sun.COM 		goto out;
50357836SJohn.Forte@Sun.COM 	}
50367836SJohn.Forte@Sun.COM 
50377836SJohn.Forte@Sun.COM 	/*
50387836SJohn.Forte@Sun.COM 	 * We have the guid list, now get the corresponding
50397836SJohn.Forte@Sun.COM 	 * view entries for each guid
50407836SJohn.Forte@Sun.COM 	 */
50417836SJohn.Forte@Sun.COM 	for (i = 0; i < guidList->cnt; i++) {
50427836SJohn.Forte@Sun.COM 		ret = psGetViewEntryList(&guidList->guid[i], &viewEntryList);
50437836SJohn.Forte@Sun.COM 		switch (ret) {
50447836SJohn.Forte@Sun.COM 			case STMF_PS_SUCCESS:
50457836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_SUCCESS;
50467836SJohn.Forte@Sun.COM 				break;
50477836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_NOT_FOUND:
50487836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
50497836SJohn.Forte@Sun.COM 				break;
50507836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_BUSY:
50517836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
50527836SJohn.Forte@Sun.COM 				break;
50537836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_SERVICE_NOT_FOUND:
50547836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_SERVICE_NOT_FOUND;
50557836SJohn.Forte@Sun.COM 				break;
50567836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_VERSION_MISMATCH:
50577836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_SERVICE_DATA_VERSION;
50587836SJohn.Forte@Sun.COM 				break;
50597836SJohn.Forte@Sun.COM 			default:
50607836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
50617836SJohn.Forte@Sun.COM 				break;
50627836SJohn.Forte@Sun.COM 		}
50637836SJohn.Forte@Sun.COM 		if (ret != STMF_STATUS_SUCCESS) {
50647836SJohn.Forte@Sun.COM 			goto out;
50657836SJohn.Forte@Sun.COM 		}
50667836SJohn.Forte@Sun.COM 		for (j = 0; j < viewEntryList->cnt; j++) {
50677836SJohn.Forte@Sun.COM 			ret = addViewEntryIoctl(fd, &guidList->guid[i],
50687836SJohn.Forte@Sun.COM 			    &viewEntryList->ve[j]);
50697836SJohn.Forte@Sun.COM 			if (ret != STMF_STATUS_SUCCESS) {
50707836SJohn.Forte@Sun.COM 				goto out;
50717836SJohn.Forte@Sun.COM 			}
50727836SJohn.Forte@Sun.COM 		}
50737836SJohn.Forte@Sun.COM 	}
50747836SJohn.Forte@Sun.COM 
50757836SJohn.Forte@Sun.COM 	/* get the list of providers that have data */
50767836SJohn.Forte@Sun.COM 	ret = psGetProviderDataList(&providerList);
50777836SJohn.Forte@Sun.COM 	switch (ret) {
50787836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
50797836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
50807836SJohn.Forte@Sun.COM 			break;
50817836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
50827836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
50837836SJohn.Forte@Sun.COM 			break;
50847836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
50857836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
50867836SJohn.Forte@Sun.COM 			break;
50877836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
50887836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
50897836SJohn.Forte@Sun.COM 			break;
50907836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
50917836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
50927836SJohn.Forte@Sun.COM 			break;
50937836SJohn.Forte@Sun.COM 		default:
50947836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
50957836SJohn.Forte@Sun.COM 			break;
50967836SJohn.Forte@Sun.COM 	}
50977836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
50987836SJohn.Forte@Sun.COM 		goto out;
50997836SJohn.Forte@Sun.COM 	}
51007836SJohn.Forte@Sun.COM 
51017836SJohn.Forte@Sun.COM 	for (i = 0; i < providerList->cnt; i++) {
51027836SJohn.Forte@Sun.COM 		providerType = providerList->provider[i].providerType;
51037836SJohn.Forte@Sun.COM 		ret = psGetProviderData(providerList->provider[i].name,
51047836SJohn.Forte@Sun.COM 		    &nvl, providerType, NULL);
51057836SJohn.Forte@Sun.COM 		switch (ret) {
51067836SJohn.Forte@Sun.COM 			case STMF_PS_SUCCESS:
51077836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_SUCCESS;
51087836SJohn.Forte@Sun.COM 				break;
51097836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_NOT_FOUND:
51107836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_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 				ret = STMF_STATUS_ERROR;
51237836SJohn.Forte@Sun.COM 				break;
51247836SJohn.Forte@Sun.COM 		}
51257836SJohn.Forte@Sun.COM 		if (ret != STMF_STATUS_SUCCESS) {
51267836SJohn.Forte@Sun.COM 			goto out;
51277836SJohn.Forte@Sun.COM 		}
51287836SJohn.Forte@Sun.COM 
51297836SJohn.Forte@Sun.COM 		/* call setProviderData */
51307836SJohn.Forte@Sun.COM 		ret = setProviderData(fd, providerList->provider[i].name, nvl,
51319585STim.Szeto@Sun.COM 		    providerType, NULL);
51327836SJohn.Forte@Sun.COM 		switch (ret) {
51337836SJohn.Forte@Sun.COM 			case STMF_PS_SUCCESS:
51347836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_SUCCESS;
51357836SJohn.Forte@Sun.COM 				break;
51367836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_NOT_FOUND:
51377836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
51387836SJohn.Forte@Sun.COM 				break;
51397836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_BUSY:
51407836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
51417836SJohn.Forte@Sun.COM 				break;
51427836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_SERVICE_NOT_FOUND:
51437836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_SERVICE_NOT_FOUND;
51447836SJohn.Forte@Sun.COM 				break;
51457836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_VERSION_MISMATCH:
51467836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_SERVICE_DATA_VERSION;
51477836SJohn.Forte@Sun.COM 				break;
51487836SJohn.Forte@Sun.COM 			default:
51497836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
51507836SJohn.Forte@Sun.COM 				break;
51517836SJohn.Forte@Sun.COM 		}
51527836SJohn.Forte@Sun.COM 		if (ret != STMF_STATUS_SUCCESS) {
51537836SJohn.Forte@Sun.COM 			goto out;
51547836SJohn.Forte@Sun.COM 		}
51557836SJohn.Forte@Sun.COM 
51567836SJohn.Forte@Sun.COM 		nvlist_free(nvl);
51577836SJohn.Forte@Sun.COM 		nvl = NULL;
51587836SJohn.Forte@Sun.COM 	}
51597836SJohn.Forte@Sun.COM out:
51607836SJohn.Forte@Sun.COM 	if (groupList != NULL) {
51617836SJohn.Forte@Sun.COM 		free(groupList);
51627836SJohn.Forte@Sun.COM 	}
51637836SJohn.Forte@Sun.COM 	if (guidList != NULL) {
51647836SJohn.Forte@Sun.COM 		free(guidList);
51657836SJohn.Forte@Sun.COM 	}
51667836SJohn.Forte@Sun.COM 	if (viewEntryList != NULL) {
51677836SJohn.Forte@Sun.COM 		free(viewEntryList);
51687836SJohn.Forte@Sun.COM 	}
51697836SJohn.Forte@Sun.COM 	if (nvl != NULL) {
51707836SJohn.Forte@Sun.COM 		nvlist_free(nvl);
51717836SJohn.Forte@Sun.COM 	}
51727836SJohn.Forte@Sun.COM 	return (ret);
51737836SJohn.Forte@Sun.COM }
51747836SJohn.Forte@Sun.COM 
51757836SJohn.Forte@Sun.COM /*
517610725SJohn.Forte@Sun.COM  * stmfGetAluaState
517710725SJohn.Forte@Sun.COM  *
517810725SJohn.Forte@Sun.COM  * Purpose - Get the alua state
517910725SJohn.Forte@Sun.COM  *
518010725SJohn.Forte@Sun.COM  */
518110725SJohn.Forte@Sun.COM int
518210725SJohn.Forte@Sun.COM stmfGetAluaState(boolean_t *enabled, uint32_t *node)
518310725SJohn.Forte@Sun.COM {
518410725SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
518510725SJohn.Forte@Sun.COM 	int fd;
518610725SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl = {0};
518710725SJohn.Forte@Sun.COM 	stmf_alua_state_desc_t alua_state = {0};
518810725SJohn.Forte@Sun.COM 	int ioctlRet;
518910725SJohn.Forte@Sun.COM 
519010725SJohn.Forte@Sun.COM 	if (enabled == NULL || node == NULL) {
519110725SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
519210725SJohn.Forte@Sun.COM 	}
519310725SJohn.Forte@Sun.COM 
519410725SJohn.Forte@Sun.COM 	/*
519510725SJohn.Forte@Sun.COM 	 * Open control node for stmf
519610725SJohn.Forte@Sun.COM 	 */
519710725SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
519810725SJohn.Forte@Sun.COM 		return (ret);
519910725SJohn.Forte@Sun.COM 
520010725SJohn.Forte@Sun.COM 	/*
520110725SJohn.Forte@Sun.COM 	 * Issue ioctl to get the stmf state
520210725SJohn.Forte@Sun.COM 	 */
520310725SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
520410725SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = sizeof (alua_state);
520510725SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&alua_state;
520610725SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_GET_ALUA_STATE, &stmfIoctl);
520710725SJohn.Forte@Sun.COM 
520810725SJohn.Forte@Sun.COM 	(void) close(fd);
520910725SJohn.Forte@Sun.COM 
521010725SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
521110725SJohn.Forte@Sun.COM 		switch (errno) {
521210725SJohn.Forte@Sun.COM 			case EBUSY:
521310725SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
521410725SJohn.Forte@Sun.COM 				break;
521510725SJohn.Forte@Sun.COM 			case EPERM:
521610725SJohn.Forte@Sun.COM 			case EACCES:
521710725SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
521810725SJohn.Forte@Sun.COM 				break;
521910725SJohn.Forte@Sun.COM 			default:
522010725SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
522110725SJohn.Forte@Sun.COM 				    "getStmfState:ioctl errno(%d)", errno);
522210725SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
522310725SJohn.Forte@Sun.COM 				break;
522410725SJohn.Forte@Sun.COM 		}
522510725SJohn.Forte@Sun.COM 	} else {
522610725SJohn.Forte@Sun.COM 		if (alua_state.alua_state == 1) {
522710725SJohn.Forte@Sun.COM 			*enabled = B_TRUE;
522810725SJohn.Forte@Sun.COM 		} else {
522910725SJohn.Forte@Sun.COM 			*enabled = B_FALSE;
523010725SJohn.Forte@Sun.COM 		}
523110725SJohn.Forte@Sun.COM 		*node = alua_state.alua_node;
523210725SJohn.Forte@Sun.COM 	}
523310725SJohn.Forte@Sun.COM 
523410725SJohn.Forte@Sun.COM 	return (ret);
523510725SJohn.Forte@Sun.COM }
523610725SJohn.Forte@Sun.COM 
523710725SJohn.Forte@Sun.COM /*
523810725SJohn.Forte@Sun.COM  * stmfSetAluaState
523910725SJohn.Forte@Sun.COM  *
524010725SJohn.Forte@Sun.COM  * Purpose - set the alua state to enabled/disabled
524110725SJohn.Forte@Sun.COM  *
524210725SJohn.Forte@Sun.COM  */
524310725SJohn.Forte@Sun.COM int
524410725SJohn.Forte@Sun.COM stmfSetAluaState(boolean_t enabled, uint32_t node)
524510725SJohn.Forte@Sun.COM {
524610725SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
524710725SJohn.Forte@Sun.COM 	int fd;
524810725SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl = {0};
524910725SJohn.Forte@Sun.COM 	stmf_alua_state_desc_t alua_state = {0};
525010725SJohn.Forte@Sun.COM 	int ioctlRet;
525110725SJohn.Forte@Sun.COM 
525210725SJohn.Forte@Sun.COM 	if ((enabled != B_TRUE && enabled != B_FALSE) || (node > 1)) {
525310725SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
525410725SJohn.Forte@Sun.COM 	}
525510725SJohn.Forte@Sun.COM 
525610725SJohn.Forte@Sun.COM 	if (enabled) {
525710725SJohn.Forte@Sun.COM 		alua_state.alua_state = 1;
525810725SJohn.Forte@Sun.COM 	}
525910725SJohn.Forte@Sun.COM 
526010725SJohn.Forte@Sun.COM 	alua_state.alua_node = node;
526110725SJohn.Forte@Sun.COM 
526210725SJohn.Forte@Sun.COM 	/*
526310725SJohn.Forte@Sun.COM 	 * Open control node for stmf
526410725SJohn.Forte@Sun.COM 	 */
526510725SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
526610725SJohn.Forte@Sun.COM 		return (ret);
526710725SJohn.Forte@Sun.COM 
526810725SJohn.Forte@Sun.COM 	/*
526910725SJohn.Forte@Sun.COM 	 * Issue ioctl to get the stmf state
527010725SJohn.Forte@Sun.COM 	 */
527110725SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
527210725SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (alua_state);
527310725SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&alua_state;
527410725SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_SET_ALUA_STATE, &stmfIoctl);
527510725SJohn.Forte@Sun.COM 
527610725SJohn.Forte@Sun.COM 	(void) close(fd);
527710725SJohn.Forte@Sun.COM 
527810725SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
527910725SJohn.Forte@Sun.COM 		switch (errno) {
528010725SJohn.Forte@Sun.COM 			case EBUSY:
528110725SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
528210725SJohn.Forte@Sun.COM 				break;
528310725SJohn.Forte@Sun.COM 			case EPERM:
528410725SJohn.Forte@Sun.COM 			case EACCES:
528510725SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
528610725SJohn.Forte@Sun.COM 				break;
528710725SJohn.Forte@Sun.COM 			default:
528810725SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
528910725SJohn.Forte@Sun.COM 				    "getStmfState:ioctl errno(%d)", errno);
529010725SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
529110725SJohn.Forte@Sun.COM 				break;
529210725SJohn.Forte@Sun.COM 		}
529310725SJohn.Forte@Sun.COM 	}
529411116SJohn.Forte@Sun.COM 	if (!enabled && ret == STMF_STATUS_SUCCESS) {
529510725SJohn.Forte@Sun.COM 		deleteNonActiveLus();
529610725SJohn.Forte@Sun.COM 	}
529710725SJohn.Forte@Sun.COM 
529810725SJohn.Forte@Sun.COM 	return (ret);
529910725SJohn.Forte@Sun.COM }
530010725SJohn.Forte@Sun.COM 
530110725SJohn.Forte@Sun.COM static void
530210725SJohn.Forte@Sun.COM deleteNonActiveLus()
530310725SJohn.Forte@Sun.COM {
530410725SJohn.Forte@Sun.COM 	int stmfRet;
530510725SJohn.Forte@Sun.COM 	int i;
530610725SJohn.Forte@Sun.COM 	stmfGuidList *luList;
530710725SJohn.Forte@Sun.COM 	luResource hdl = NULL;
530810725SJohn.Forte@Sun.COM 	char propVal[10];
530910725SJohn.Forte@Sun.COM 	size_t propValSize = sizeof (propVal);
531010725SJohn.Forte@Sun.COM 
531110725SJohn.Forte@Sun.COM 	stmfRet = stmfGetLogicalUnitList(&luList);
531210725SJohn.Forte@Sun.COM 	if (stmfRet != STMF_STATUS_SUCCESS) {
531310725SJohn.Forte@Sun.COM 		return;
531410725SJohn.Forte@Sun.COM 	}
531510725SJohn.Forte@Sun.COM 
531610725SJohn.Forte@Sun.COM 	for (i = 0; i < luList->cnt; i++) {
531710725SJohn.Forte@Sun.COM 		stmfRet = stmfGetLuResource(&luList->guid[i], &hdl);
531810725SJohn.Forte@Sun.COM 		if (stmfRet != STMF_STATUS_SUCCESS) {
531910725SJohn.Forte@Sun.COM 			goto err;
532010725SJohn.Forte@Sun.COM 		}
532110725SJohn.Forte@Sun.COM 		stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_ACCESS_STATE, propVal,
532210725SJohn.Forte@Sun.COM 		    &propValSize);
532310725SJohn.Forte@Sun.COM 		if (stmfRet != STMF_STATUS_SUCCESS) {
532410725SJohn.Forte@Sun.COM 			goto err;
532510725SJohn.Forte@Sun.COM 		}
532610725SJohn.Forte@Sun.COM 		if (propVal[0] == '0') {
532710725SJohn.Forte@Sun.COM 			(void) stmfFreeLuResource(hdl);
532810725SJohn.Forte@Sun.COM 			hdl = NULL;
532910725SJohn.Forte@Sun.COM 			continue;
533010725SJohn.Forte@Sun.COM 		}
533110725SJohn.Forte@Sun.COM 		(void) stmfDeleteLu(&luList->guid[i]);
533210725SJohn.Forte@Sun.COM 		(void) stmfFreeLuResource(hdl);
533310725SJohn.Forte@Sun.COM 		hdl = NULL;
533410725SJohn.Forte@Sun.COM 	}
533510725SJohn.Forte@Sun.COM 
533610725SJohn.Forte@Sun.COM err:
533710725SJohn.Forte@Sun.COM 	stmfFreeMemory(luList);
533810725SJohn.Forte@Sun.COM 	(void) stmfFreeLuResource(hdl);
533910725SJohn.Forte@Sun.COM }
534010725SJohn.Forte@Sun.COM 
534110725SJohn.Forte@Sun.COM /*
53427836SJohn.Forte@Sun.COM  * stmfLoadConfig
53437836SJohn.Forte@Sun.COM  *
53447836SJohn.Forte@Sun.COM  * Purpose - load the configuration data from smf into stmf
53457836SJohn.Forte@Sun.COM  *
53467836SJohn.Forte@Sun.COM  */
53477836SJohn.Forte@Sun.COM int
53487836SJohn.Forte@Sun.COM stmfLoadConfig(void)
53497836SJohn.Forte@Sun.COM {
53509585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
53517836SJohn.Forte@Sun.COM 	int fd;
53527836SJohn.Forte@Sun.COM 	stmf_state_desc_t stmfStateSet;
53537836SJohn.Forte@Sun.COM 	stmfState state;
53547836SJohn.Forte@Sun.COM 
53559585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
53569585STim.Szeto@Sun.COM 		stmfStateSet.state = STMF_STATE_OFFLINE;
535710560SSusan.Gleeson@Sun.COM 
53589585STim.Szeto@Sun.COM 		if ((ret = openStmf(OPEN_EXCL_STMF, &fd))
53599585STim.Szeto@Sun.COM 		    != STMF_STATUS_SUCCESS) {
53609585STim.Szeto@Sun.COM 			return (ret);
53619585STim.Szeto@Sun.COM 		}
536210560SSusan.Gleeson@Sun.COM 		/*
536310560SSusan.Gleeson@Sun.COM 		 * Configuration not stored persistently; nothing to
536410560SSusan.Gleeson@Sun.COM 		 * initialize so do not set to STMF_CONFIG_INIT.
536510560SSusan.Gleeson@Sun.COM 		 */
53669585STim.Szeto@Sun.COM 		stmfStateSet.config_state = STMF_CONFIG_INIT_DONE;
53679585STim.Szeto@Sun.COM 		goto done;
53689585STim.Szeto@Sun.COM 	}
53697836SJohn.Forte@Sun.COM 
53707836SJohn.Forte@Sun.COM 	/* Check to ensure service exists */
53717836SJohn.Forte@Sun.COM 	if (psCheckService() != STMF_STATUS_SUCCESS) {
53727836SJohn.Forte@Sun.COM 		return (STMF_ERROR_SERVICE_NOT_FOUND);
53737836SJohn.Forte@Sun.COM 	}
53747836SJohn.Forte@Sun.COM 
53757836SJohn.Forte@Sun.COM 	ret = stmfGetState(&state);
53767836SJohn.Forte@Sun.COM 	if (ret == STMF_STATUS_SUCCESS) {
53777836SJohn.Forte@Sun.COM 		if (state.operationalState != STMF_SERVICE_STATE_OFFLINE) {
53787836SJohn.Forte@Sun.COM 			return (STMF_ERROR_SERVICE_ONLINE);
53797836SJohn.Forte@Sun.COM 		}
53807836SJohn.Forte@Sun.COM 	} else {
53817836SJohn.Forte@Sun.COM 		return (STMF_STATUS_ERROR);
53827836SJohn.Forte@Sun.COM 	}
53837836SJohn.Forte@Sun.COM 
53847836SJohn.Forte@Sun.COM 
53857836SJohn.Forte@Sun.COM 	stmfStateSet.state = STMF_STATE_OFFLINE;
53867836SJohn.Forte@Sun.COM 	stmfStateSet.config_state = STMF_CONFIG_INIT;
53877836SJohn.Forte@Sun.COM 
53887836SJohn.Forte@Sun.COM 	/*
53897836SJohn.Forte@Sun.COM 	 * Open control node for stmf
53907836SJohn.Forte@Sun.COM 	 */
53917836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
53927836SJohn.Forte@Sun.COM 		return (ret);
53937836SJohn.Forte@Sun.COM 
53947836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE);
53957836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
53967836SJohn.Forte@Sun.COM 		goto done;
53977836SJohn.Forte@Sun.COM 	}
53987836SJohn.Forte@Sun.COM 
53997836SJohn.Forte@Sun.COM 	/* Load the persistent configuration data */
54007836SJohn.Forte@Sun.COM 	ret = loadStore(fd);
54017836SJohn.Forte@Sun.COM 	if (ret != 0) {
54027836SJohn.Forte@Sun.COM 		goto done;
54037836SJohn.Forte@Sun.COM 	}
54047836SJohn.Forte@Sun.COM 
54057836SJohn.Forte@Sun.COM 	stmfStateSet.state = STMF_STATE_OFFLINE;
54067836SJohn.Forte@Sun.COM 	stmfStateSet.config_state = STMF_CONFIG_INIT_DONE;
54077836SJohn.Forte@Sun.COM 
54087836SJohn.Forte@Sun.COM done:
54097836SJohn.Forte@Sun.COM 	if (ret == STMF_STATUS_SUCCESS) {
54107836SJohn.Forte@Sun.COM 		ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE);
54117836SJohn.Forte@Sun.COM 	}
54127836SJohn.Forte@Sun.COM 	(void) close(fd);
54137836SJohn.Forte@Sun.COM 	return (ret);
54147836SJohn.Forte@Sun.COM }
54157836SJohn.Forte@Sun.COM 
54169585STim.Szeto@Sun.COM 
54177836SJohn.Forte@Sun.COM /*
54187836SJohn.Forte@Sun.COM  * getStmfState
54197836SJohn.Forte@Sun.COM  *
54207836SJohn.Forte@Sun.COM  * stmfState - pointer to stmf_state_desc_t structure. Will contain the state
54217836SJohn.Forte@Sun.COM  *             information of the stmf service on success.
54227836SJohn.Forte@Sun.COM  */
54237836SJohn.Forte@Sun.COM static int
54247836SJohn.Forte@Sun.COM getStmfState(stmf_state_desc_t *stmfState)
54257836SJohn.Forte@Sun.COM {
54267836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
54277836SJohn.Forte@Sun.COM 	int fd;
54287836SJohn.Forte@Sun.COM 	int ioctlRet;
54297836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
54307836SJohn.Forte@Sun.COM 
54317836SJohn.Forte@Sun.COM 	/*
54327836SJohn.Forte@Sun.COM 	 * Open control node for stmf
54337836SJohn.Forte@Sun.COM 	 */
54347836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
54357836SJohn.Forte@Sun.COM 		return (ret);
54367836SJohn.Forte@Sun.COM 
54377836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
54387836SJohn.Forte@Sun.COM 	/*
54397836SJohn.Forte@Sun.COM 	 * Issue ioctl to get the stmf state
54407836SJohn.Forte@Sun.COM 	 */
54417836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
54427836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (stmf_state_desc_t);
54437836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)stmfState;
54447836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = sizeof (stmf_state_desc_t);
54457836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)stmfState;
54467836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_GET_STMF_STATE, &stmfIoctl);
54477836SJohn.Forte@Sun.COM 
54487836SJohn.Forte@Sun.COM 	(void) close(fd);
54497836SJohn.Forte@Sun.COM 
54507836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
54517836SJohn.Forte@Sun.COM 		switch (errno) {
54527836SJohn.Forte@Sun.COM 			case EBUSY:
54537836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
54547836SJohn.Forte@Sun.COM 				break;
54557836SJohn.Forte@Sun.COM 			case EPERM:
54567836SJohn.Forte@Sun.COM 			case EACCES:
54577836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
54587836SJohn.Forte@Sun.COM 				break;
54597836SJohn.Forte@Sun.COM 			default:
54607836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
54617836SJohn.Forte@Sun.COM 				    "getStmfState:ioctl errno(%d)", errno);
54627836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
54637836SJohn.Forte@Sun.COM 				break;
54647836SJohn.Forte@Sun.COM 		}
54657836SJohn.Forte@Sun.COM 	}
54667836SJohn.Forte@Sun.COM 	return (ret);
54677836SJohn.Forte@Sun.COM }
54687836SJohn.Forte@Sun.COM 
54697836SJohn.Forte@Sun.COM 
54707836SJohn.Forte@Sun.COM /*
54717836SJohn.Forte@Sun.COM  * setStmfState
54727836SJohn.Forte@Sun.COM  *
54737836SJohn.Forte@Sun.COM  * stmfState - pointer to caller set state structure
54747836SJohn.Forte@Sun.COM  * objectType - one of:
54757836SJohn.Forte@Sun.COM  *		LOGICAL_UNIT_TYPE
54767836SJohn.Forte@Sun.COM  *		TARGET_TYPE
54777836SJohn.Forte@Sun.COM  *		STMF_SERVICE_TYPE
54787836SJohn.Forte@Sun.COM  */
54797836SJohn.Forte@Sun.COM static int
54807836SJohn.Forte@Sun.COM setStmfState(int fd, stmf_state_desc_t *stmfState, int objectType)
54817836SJohn.Forte@Sun.COM {
54827836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
54837836SJohn.Forte@Sun.COM 	int ioctlRet;
54847836SJohn.Forte@Sun.COM 	int cmd;
54857836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
54867836SJohn.Forte@Sun.COM 
54877836SJohn.Forte@Sun.COM 	switch (objectType) {
54887836SJohn.Forte@Sun.COM 		case LOGICAL_UNIT_TYPE:
54897836SJohn.Forte@Sun.COM 			cmd = STMF_IOCTL_SET_LU_STATE;
54907836SJohn.Forte@Sun.COM 			break;
54917836SJohn.Forte@Sun.COM 		case TARGET_TYPE:
54927836SJohn.Forte@Sun.COM 			cmd = STMF_IOCTL_SET_TARGET_PORT_STATE;
54937836SJohn.Forte@Sun.COM 			break;
54947836SJohn.Forte@Sun.COM 		case STMF_SERVICE_TYPE:
54957836SJohn.Forte@Sun.COM 			cmd = STMF_IOCTL_SET_STMF_STATE;
54967836SJohn.Forte@Sun.COM 			break;
54977836SJohn.Forte@Sun.COM 		default:
54987836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
54997836SJohn.Forte@Sun.COM 			goto done;
55007836SJohn.Forte@Sun.COM 	}
55017836SJohn.Forte@Sun.COM 
55027836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
55037836SJohn.Forte@Sun.COM 	/*
55047836SJohn.Forte@Sun.COM 	 * Issue ioctl to set the stmf state
55057836SJohn.Forte@Sun.COM 	 */
55067836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
55077836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (stmf_state_desc_t);
55087836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)stmfState;
55097836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
55107836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
55117836SJohn.Forte@Sun.COM 		switch (errno) {
55127836SJohn.Forte@Sun.COM 			case EBUSY:
55137836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
55147836SJohn.Forte@Sun.COM 				break;
55159585STim.Szeto@Sun.COM 			case EPERM:
55167836SJohn.Forte@Sun.COM 			case EACCES:
55177836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
55187836SJohn.Forte@Sun.COM 				break;
55197836SJohn.Forte@Sun.COM 			case ENOENT:
55207836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
55217836SJohn.Forte@Sun.COM 				break;
55227836SJohn.Forte@Sun.COM 			default:
55237836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
55247836SJohn.Forte@Sun.COM 				    "setStmfState:ioctl errno(%d)", errno);
55257836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
55267836SJohn.Forte@Sun.COM 				break;
55277836SJohn.Forte@Sun.COM 		}
55287836SJohn.Forte@Sun.COM 	}
55297836SJohn.Forte@Sun.COM done:
55307836SJohn.Forte@Sun.COM 	return (ret);
55317836SJohn.Forte@Sun.COM }
55327836SJohn.Forte@Sun.COM 
55337836SJohn.Forte@Sun.COM /*
55347836SJohn.Forte@Sun.COM  * stmfOnline
55357836SJohn.Forte@Sun.COM  *
55367836SJohn.Forte@Sun.COM  * Purpose: Online stmf service
55377836SJohn.Forte@Sun.COM  *
55387836SJohn.Forte@Sun.COM  */
55397836SJohn.Forte@Sun.COM int
55407836SJohn.Forte@Sun.COM stmfOnline(void)
55417836SJohn.Forte@Sun.COM {
55427836SJohn.Forte@Sun.COM 	int ret;
55437836SJohn.Forte@Sun.COM 	int fd;
55447836SJohn.Forte@Sun.COM 	stmfState state;
55457836SJohn.Forte@Sun.COM 	stmf_state_desc_t iState;
55467836SJohn.Forte@Sun.COM 
55477836SJohn.Forte@Sun.COM 	ret = stmfGetState(&state);
55487836SJohn.Forte@Sun.COM 	if (ret == STMF_STATUS_SUCCESS) {
55497836SJohn.Forte@Sun.COM 		if (state.operationalState == STMF_SERVICE_STATE_ONLINE) {
55507836SJohn.Forte@Sun.COM 			return (STMF_ERROR_SERVICE_ONLINE);
55517836SJohn.Forte@Sun.COM 		}
55527836SJohn.Forte@Sun.COM 	} else {
55537836SJohn.Forte@Sun.COM 		return (STMF_STATUS_ERROR);
55547836SJohn.Forte@Sun.COM 	}
55557836SJohn.Forte@Sun.COM 	iState.state = STMF_STATE_ONLINE;
55567836SJohn.Forte@Sun.COM 	iState.config_state = STMF_CONFIG_NONE;
55577836SJohn.Forte@Sun.COM 	/*
55587836SJohn.Forte@Sun.COM 	 * Open control node for stmf
55597836SJohn.Forte@Sun.COM 	 * to make call to setStmfState()
55607836SJohn.Forte@Sun.COM 	 */
55617836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
55627836SJohn.Forte@Sun.COM 		return (ret);
55637836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &iState, STMF_SERVICE_TYPE);
55647836SJohn.Forte@Sun.COM 	(void) close(fd);
55657836SJohn.Forte@Sun.COM 	return (ret);
55667836SJohn.Forte@Sun.COM }
55677836SJohn.Forte@Sun.COM 
55687836SJohn.Forte@Sun.COM /*
55697836SJohn.Forte@Sun.COM  * stmfOffline
55707836SJohn.Forte@Sun.COM  *
55717836SJohn.Forte@Sun.COM  * Purpose: Offline stmf service
55727836SJohn.Forte@Sun.COM  *
55737836SJohn.Forte@Sun.COM  */
55747836SJohn.Forte@Sun.COM int
55757836SJohn.Forte@Sun.COM stmfOffline(void)
55767836SJohn.Forte@Sun.COM {
55777836SJohn.Forte@Sun.COM 	int ret;
55787836SJohn.Forte@Sun.COM 	int fd;
55797836SJohn.Forte@Sun.COM 	stmfState state;
55807836SJohn.Forte@Sun.COM 	stmf_state_desc_t iState;
55817836SJohn.Forte@Sun.COM 
55827836SJohn.Forte@Sun.COM 	ret = stmfGetState(&state);
55837836SJohn.Forte@Sun.COM 	if (ret == STMF_STATUS_SUCCESS) {
55847836SJohn.Forte@Sun.COM 		if (state.operationalState == STMF_SERVICE_STATE_OFFLINE) {
55857836SJohn.Forte@Sun.COM 			return (STMF_ERROR_SERVICE_OFFLINE);
55867836SJohn.Forte@Sun.COM 		}
55877836SJohn.Forte@Sun.COM 	} else {
55887836SJohn.Forte@Sun.COM 		return (STMF_STATUS_ERROR);
55897836SJohn.Forte@Sun.COM 	}
55907836SJohn.Forte@Sun.COM 	iState.state = STMF_STATE_OFFLINE;
55917836SJohn.Forte@Sun.COM 	iState.config_state = STMF_CONFIG_NONE;
55927836SJohn.Forte@Sun.COM 
55937836SJohn.Forte@Sun.COM 	/*
55947836SJohn.Forte@Sun.COM 	 * Open control node for stmf
55957836SJohn.Forte@Sun.COM 	 * to make call to setStmfState()
55967836SJohn.Forte@Sun.COM 	 */
55977836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
55987836SJohn.Forte@Sun.COM 		return (ret);
55997836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &iState, STMF_SERVICE_TYPE);
56007836SJohn.Forte@Sun.COM 	(void) close(fd);
56017836SJohn.Forte@Sun.COM 	return (ret);
56027836SJohn.Forte@Sun.COM }
56037836SJohn.Forte@Sun.COM 
56047836SJohn.Forte@Sun.COM 
56057836SJohn.Forte@Sun.COM /*
56067836SJohn.Forte@Sun.COM  * stmfOfflineTarget
56077836SJohn.Forte@Sun.COM  *
56087836SJohn.Forte@Sun.COM  * Purpose: Change state of target to offline
56097836SJohn.Forte@Sun.COM  *
56107836SJohn.Forte@Sun.COM  * devid - devid of the target to offline
56117836SJohn.Forte@Sun.COM  */
56127836SJohn.Forte@Sun.COM int
56137836SJohn.Forte@Sun.COM stmfOfflineTarget(stmfDevid *devid)
56147836SJohn.Forte@Sun.COM {
56157836SJohn.Forte@Sun.COM 	stmf_state_desc_t targetState;
56167836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
56177836SJohn.Forte@Sun.COM 	int fd;
56187836SJohn.Forte@Sun.COM 
56197836SJohn.Forte@Sun.COM 	if (devid == NULL) {
56207836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
56217836SJohn.Forte@Sun.COM 	}
56227836SJohn.Forte@Sun.COM 	bzero(&targetState, sizeof (targetState));
56237836SJohn.Forte@Sun.COM 
56247836SJohn.Forte@Sun.COM 	targetState.state = STMF_STATE_OFFLINE;
56257836SJohn.Forte@Sun.COM 	targetState.ident[IDENT_LENGTH_BYTE] = devid->identLength;
56267836SJohn.Forte@Sun.COM 	bcopy(&(devid->ident), &targetState.ident[IDENT_LENGTH_BYTE + 1],
56277836SJohn.Forte@Sun.COM 	    devid->identLength);
56287836SJohn.Forte@Sun.COM 	/*
56297836SJohn.Forte@Sun.COM 	 * Open control node for stmf
56307836SJohn.Forte@Sun.COM 	 * to make call to setStmfState()
56317836SJohn.Forte@Sun.COM 	 */
56327836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
56337836SJohn.Forte@Sun.COM 		return (ret);
56347836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &targetState, TARGET_TYPE);
56357836SJohn.Forte@Sun.COM 	(void) close(fd);
56367836SJohn.Forte@Sun.COM 	return (ret);
56377836SJohn.Forte@Sun.COM }
56387836SJohn.Forte@Sun.COM 
56397836SJohn.Forte@Sun.COM /*
56407836SJohn.Forte@Sun.COM  * stmfOfflineLogicalUnit
56417836SJohn.Forte@Sun.COM  *
56427836SJohn.Forte@Sun.COM  * Purpose: Change state of logical unit to offline
56437836SJohn.Forte@Sun.COM  *
56447836SJohn.Forte@Sun.COM  * lu - guid of the logical unit to offline
56457836SJohn.Forte@Sun.COM  */
56467836SJohn.Forte@Sun.COM int
56477836SJohn.Forte@Sun.COM stmfOfflineLogicalUnit(stmfGuid *lu)
56487836SJohn.Forte@Sun.COM {
56497836SJohn.Forte@Sun.COM 	stmf_state_desc_t luState;
56507836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
56517836SJohn.Forte@Sun.COM 	int fd;
56527836SJohn.Forte@Sun.COM 
56537836SJohn.Forte@Sun.COM 	if (lu == NULL) {
56547836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
56557836SJohn.Forte@Sun.COM 	}
56567836SJohn.Forte@Sun.COM 
56577836SJohn.Forte@Sun.COM 	bzero(&luState, sizeof (luState));
56587836SJohn.Forte@Sun.COM 
56597836SJohn.Forte@Sun.COM 	luState.state = STMF_STATE_OFFLINE;
56607836SJohn.Forte@Sun.COM 	bcopy(lu, &luState.ident, sizeof (stmfGuid));
56617836SJohn.Forte@Sun.COM 	/*
56627836SJohn.Forte@Sun.COM 	 * Open control node for stmf
56637836SJohn.Forte@Sun.COM 	 * to make call to setStmfState()
56647836SJohn.Forte@Sun.COM 	 */
56657836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
56667836SJohn.Forte@Sun.COM 		return (ret);
56677836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &luState, LOGICAL_UNIT_TYPE);
56687836SJohn.Forte@Sun.COM 	(void) close(fd);
56697836SJohn.Forte@Sun.COM 	return (ret);
56707836SJohn.Forte@Sun.COM }
56717836SJohn.Forte@Sun.COM 
56727836SJohn.Forte@Sun.COM /*
56737836SJohn.Forte@Sun.COM  * stmfOnlineTarget
56747836SJohn.Forte@Sun.COM  *
56757836SJohn.Forte@Sun.COM  * Purpose: Change state of target to online
56767836SJohn.Forte@Sun.COM  *
56777836SJohn.Forte@Sun.COM  * devid - devid of the target to online
56787836SJohn.Forte@Sun.COM  */
56797836SJohn.Forte@Sun.COM int
56807836SJohn.Forte@Sun.COM stmfOnlineTarget(stmfDevid *devid)
56817836SJohn.Forte@Sun.COM {
56827836SJohn.Forte@Sun.COM 	stmf_state_desc_t targetState;
56837836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
56847836SJohn.Forte@Sun.COM 	int fd;
56857836SJohn.Forte@Sun.COM 
56867836SJohn.Forte@Sun.COM 	if (devid == NULL) {
56877836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
56887836SJohn.Forte@Sun.COM 	}
56897836SJohn.Forte@Sun.COM 	bzero(&targetState, sizeof (targetState));
56907836SJohn.Forte@Sun.COM 
56917836SJohn.Forte@Sun.COM 	targetState.state = STMF_STATE_ONLINE;
56927836SJohn.Forte@Sun.COM 	targetState.ident[IDENT_LENGTH_BYTE] = devid->identLength;
56937836SJohn.Forte@Sun.COM 	bcopy(&(devid->ident), &targetState.ident[IDENT_LENGTH_BYTE + 1],
56947836SJohn.Forte@Sun.COM 	    devid->identLength);
56957836SJohn.Forte@Sun.COM 	/*
56967836SJohn.Forte@Sun.COM 	 * Open control node for stmf
56977836SJohn.Forte@Sun.COM 	 * to make call to setStmfState()
56987836SJohn.Forte@Sun.COM 	 */
56997836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
57007836SJohn.Forte@Sun.COM 		return (ret);
57017836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &targetState, TARGET_TYPE);
57027836SJohn.Forte@Sun.COM 	(void) close(fd);
57037836SJohn.Forte@Sun.COM 	return (ret);
57047836SJohn.Forte@Sun.COM }
57057836SJohn.Forte@Sun.COM 
57067836SJohn.Forte@Sun.COM /*
57077836SJohn.Forte@Sun.COM  * stmfOnlineLogicalUnit
57087836SJohn.Forte@Sun.COM  *
57097836SJohn.Forte@Sun.COM  * Purpose: Change state of logical unit to online
57107836SJohn.Forte@Sun.COM  *
57117836SJohn.Forte@Sun.COM  * lu - guid of the logical unit to online
57127836SJohn.Forte@Sun.COM  */
57137836SJohn.Forte@Sun.COM int
57147836SJohn.Forte@Sun.COM stmfOnlineLogicalUnit(stmfGuid *lu)
57157836SJohn.Forte@Sun.COM {
57167836SJohn.Forte@Sun.COM 	stmf_state_desc_t luState;
57177836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
57187836SJohn.Forte@Sun.COM 	int fd;
57197836SJohn.Forte@Sun.COM 
57207836SJohn.Forte@Sun.COM 	if (lu == NULL) {
57217836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
57227836SJohn.Forte@Sun.COM 	}
57237836SJohn.Forte@Sun.COM 
57247836SJohn.Forte@Sun.COM 	bzero(&luState, sizeof (luState));
57257836SJohn.Forte@Sun.COM 
57267836SJohn.Forte@Sun.COM 	luState.state = STMF_STATE_ONLINE;
57277836SJohn.Forte@Sun.COM 	bcopy(lu, &luState.ident, sizeof (stmfGuid));
57287836SJohn.Forte@Sun.COM 	/*
57297836SJohn.Forte@Sun.COM 	 * Open control node for stmf
57307836SJohn.Forte@Sun.COM 	 * to make call to setStmfState()
57317836SJohn.Forte@Sun.COM 	 */
57327836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
57337836SJohn.Forte@Sun.COM 		return (ret);
57347836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &luState, LOGICAL_UNIT_TYPE);
57357836SJohn.Forte@Sun.COM 	(void) close(fd);
57367836SJohn.Forte@Sun.COM 	return (ret);
57377836SJohn.Forte@Sun.COM }
57387836SJohn.Forte@Sun.COM 
57397836SJohn.Forte@Sun.COM /*
57407836SJohn.Forte@Sun.COM  * stmfRemoveFromHostGroup
57417836SJohn.Forte@Sun.COM  *
57427836SJohn.Forte@Sun.COM  * Purpose: Removes an initiator from an initiator group
57437836SJohn.Forte@Sun.COM  *
57447836SJohn.Forte@Sun.COM  * hostGroupName - name of an initiator group
57457836SJohn.Forte@Sun.COM  * hostName - name of host group member to remove
57467836SJohn.Forte@Sun.COM  */
57477836SJohn.Forte@Sun.COM int
57487836SJohn.Forte@Sun.COM stmfRemoveFromHostGroup(stmfGroupName *hostGroupName, stmfDevid *hostName)
57497836SJohn.Forte@Sun.COM {
57507836SJohn.Forte@Sun.COM 	int ret;
57517836SJohn.Forte@Sun.COM 	int fd;
57527836SJohn.Forte@Sun.COM 
57537836SJohn.Forte@Sun.COM 	if (hostGroupName == NULL ||
57547836SJohn.Forte@Sun.COM 	    (strnlen((char *)hostGroupName, sizeof (stmfGroupName))
57557836SJohn.Forte@Sun.COM 	    == sizeof (stmfGroupName)) || hostName == NULL) {
57567836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
57577836SJohn.Forte@Sun.COM 	}
57587836SJohn.Forte@Sun.COM 
57597836SJohn.Forte@Sun.COM 	/* call init */
57607836SJohn.Forte@Sun.COM 	ret = initializeConfig();
57617836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
57627836SJohn.Forte@Sun.COM 		return (ret);
57637836SJohn.Forte@Sun.COM 	}
57647836SJohn.Forte@Sun.COM 
57657836SJohn.Forte@Sun.COM 	/*
57667836SJohn.Forte@Sun.COM 	 * Open control node for stmf
57677836SJohn.Forte@Sun.COM 	 */
57687836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
57697836SJohn.Forte@Sun.COM 		return (ret);
57707836SJohn.Forte@Sun.COM 
57717836SJohn.Forte@Sun.COM 	if ((ret = groupMemberIoctl(fd, STMF_IOCTL_REMOVE_HG_ENTRY,
57727836SJohn.Forte@Sun.COM 	    hostGroupName, hostName)) != STMF_STATUS_SUCCESS) {
57737836SJohn.Forte@Sun.COM 		goto done;
57747836SJohn.Forte@Sun.COM 	}
57757836SJohn.Forte@Sun.COM 
57769585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
57779585STim.Szeto@Sun.COM 		goto done;
57789585STim.Szeto@Sun.COM 	}
57799585STim.Szeto@Sun.COM 
57807836SJohn.Forte@Sun.COM 	ret = psRemoveHostGroupMember((char *)hostGroupName,
57817836SJohn.Forte@Sun.COM 	    (char *)hostName->ident);
57827836SJohn.Forte@Sun.COM 	switch (ret) {
57837836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
57847836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
57857836SJohn.Forte@Sun.COM 			break;
57867836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_MEMBER_NOT_FOUND:
57877836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_MEMBER_NOT_FOUND;
57887836SJohn.Forte@Sun.COM 			break;
57897836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_GROUP_NOT_FOUND:
57907836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_GROUP_NOT_FOUND;
57917836SJohn.Forte@Sun.COM 			break;
57927836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
57937836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
57947836SJohn.Forte@Sun.COM 			break;
57957836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
57967836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
57977836SJohn.Forte@Sun.COM 			break;
57987836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
57997836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
58007836SJohn.Forte@Sun.COM 			break;
58017836SJohn.Forte@Sun.COM 		default:
58027836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
58037836SJohn.Forte@Sun.COM 			    "stmfRemoveFromHostGroup"
58047836SJohn.Forte@Sun.COM 			    "psRemoveHostGroupMember:error(%d)", ret);
58057836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
58067836SJohn.Forte@Sun.COM 			break;
58077836SJohn.Forte@Sun.COM 	}
58087836SJohn.Forte@Sun.COM 
58097836SJohn.Forte@Sun.COM done:
58107836SJohn.Forte@Sun.COM 	(void) close(fd);
58117836SJohn.Forte@Sun.COM 	return (ret);
58127836SJohn.Forte@Sun.COM }
58137836SJohn.Forte@Sun.COM 
58147836SJohn.Forte@Sun.COM /*
58157836SJohn.Forte@Sun.COM  * stmfRemoveFromTargetGroup
58167836SJohn.Forte@Sun.COM  *
58177836SJohn.Forte@Sun.COM  * Purpose: Removes a local port from a local port group
58187836SJohn.Forte@Sun.COM  *
58197836SJohn.Forte@Sun.COM  * targetGroupName - name of a target group
58207836SJohn.Forte@Sun.COM  * targetName - name of target to remove
58217836SJohn.Forte@Sun.COM  */
58227836SJohn.Forte@Sun.COM int
58237836SJohn.Forte@Sun.COM stmfRemoveFromTargetGroup(stmfGroupName *targetGroupName, stmfDevid *targetName)
58247836SJohn.Forte@Sun.COM {
58257836SJohn.Forte@Sun.COM 	int ret;
58267836SJohn.Forte@Sun.COM 	int fd;
58277836SJohn.Forte@Sun.COM 
58287836SJohn.Forte@Sun.COM 	if (targetGroupName == NULL ||
58297836SJohn.Forte@Sun.COM 	    (strnlen((char *)targetGroupName, sizeof (stmfGroupName))
58307836SJohn.Forte@Sun.COM 	    == sizeof (stmfGroupName)) || targetName == NULL) {
58317836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
58327836SJohn.Forte@Sun.COM 	}
58337836SJohn.Forte@Sun.COM 
58347836SJohn.Forte@Sun.COM 	/* call init */
58357836SJohn.Forte@Sun.COM 	ret = initializeConfig();
58367836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
58377836SJohn.Forte@Sun.COM 		return (ret);
58387836SJohn.Forte@Sun.COM 	}
58397836SJohn.Forte@Sun.COM 
58407836SJohn.Forte@Sun.COM 	/*
58417836SJohn.Forte@Sun.COM 	 * Open control node for stmf
58427836SJohn.Forte@Sun.COM 	 */
58437836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
58447836SJohn.Forte@Sun.COM 		return (ret);
58457836SJohn.Forte@Sun.COM 
58467836SJohn.Forte@Sun.COM 	if ((ret = groupMemberIoctl(fd, STMF_IOCTL_REMOVE_TG_ENTRY,
58477836SJohn.Forte@Sun.COM 	    targetGroupName, targetName)) != STMF_STATUS_SUCCESS) {
58487836SJohn.Forte@Sun.COM 		goto done;
58497836SJohn.Forte@Sun.COM 	}
58507836SJohn.Forte@Sun.COM 
58519585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
58529585STim.Szeto@Sun.COM 		goto done;
58539585STim.Szeto@Sun.COM 	}
58549585STim.Szeto@Sun.COM 
58557836SJohn.Forte@Sun.COM 	ret = psRemoveTargetGroupMember((char *)targetGroupName,
58567836SJohn.Forte@Sun.COM 	    (char *)targetName->ident);
58577836SJohn.Forte@Sun.COM 	switch (ret) {
58587836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
58597836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
58607836SJohn.Forte@Sun.COM 			break;
58617836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_MEMBER_NOT_FOUND:
58627836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_MEMBER_NOT_FOUND;
58637836SJohn.Forte@Sun.COM 			break;
58647836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_GROUP_NOT_FOUND:
58657836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_GROUP_NOT_FOUND;
58667836SJohn.Forte@Sun.COM 			break;
58677836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
58687836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
58697836SJohn.Forte@Sun.COM 			break;
58707836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
58717836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
58727836SJohn.Forte@Sun.COM 			break;
58737836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
58747836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
58757836SJohn.Forte@Sun.COM 			break;
58767836SJohn.Forte@Sun.COM 		default:
58777836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
58787836SJohn.Forte@Sun.COM 			    "stmfRemoveFromTargetGroup"
58797836SJohn.Forte@Sun.COM 			    "psRemoveTargetGroupMember:error(%d)", ret);
58807836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
58817836SJohn.Forte@Sun.COM 			break;
58827836SJohn.Forte@Sun.COM 	}
58837836SJohn.Forte@Sun.COM 
58847836SJohn.Forte@Sun.COM done:
58857836SJohn.Forte@Sun.COM 	(void) close(fd);
58867836SJohn.Forte@Sun.COM 	return (ret);
58877836SJohn.Forte@Sun.COM }
58887836SJohn.Forte@Sun.COM 
58897836SJohn.Forte@Sun.COM /*
58907836SJohn.Forte@Sun.COM  * stmfRemoveViewEntry
58917836SJohn.Forte@Sun.COM  *
58927836SJohn.Forte@Sun.COM  * Purpose: Removes a view entry from a logical unit
58937836SJohn.Forte@Sun.COM  *
58947836SJohn.Forte@Sun.COM  * lu - guid of lu for which view entry is being removed
58957836SJohn.Forte@Sun.COM  * viewEntryIndex - index of view entry to remove
58967836SJohn.Forte@Sun.COM  *
58977836SJohn.Forte@Sun.COM  */
58987836SJohn.Forte@Sun.COM int
58997836SJohn.Forte@Sun.COM stmfRemoveViewEntry(stmfGuid *lu, uint32_t viewEntryIndex)
59007836SJohn.Forte@Sun.COM {
59017836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
59027836SJohn.Forte@Sun.COM 	int fd;
59037836SJohn.Forte@Sun.COM 	int ioctlRet;
59047836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
59057836SJohn.Forte@Sun.COM 	stmf_view_op_entry_t ioctlViewEntry;
59067836SJohn.Forte@Sun.COM 
59077836SJohn.Forte@Sun.COM 	if (lu == NULL) {
59087836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
59097836SJohn.Forte@Sun.COM 	}
59107836SJohn.Forte@Sun.COM 
59117836SJohn.Forte@Sun.COM 	/* call init */
59127836SJohn.Forte@Sun.COM 	ret = initializeConfig();
59137836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
59147836SJohn.Forte@Sun.COM 		return (ret);
59157836SJohn.Forte@Sun.COM 	}
59167836SJohn.Forte@Sun.COM 
59177836SJohn.Forte@Sun.COM 	/*
59187836SJohn.Forte@Sun.COM 	 * Open control node for stmf
59197836SJohn.Forte@Sun.COM 	 */
59207836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
59217836SJohn.Forte@Sun.COM 		return (ret);
59227836SJohn.Forte@Sun.COM 
59237836SJohn.Forte@Sun.COM 	bzero(&ioctlViewEntry, sizeof (ioctlViewEntry));
59247836SJohn.Forte@Sun.COM 	ioctlViewEntry.ve_ndx_valid = B_TRUE;
59257836SJohn.Forte@Sun.COM 	ioctlViewEntry.ve_ndx = viewEntryIndex;
59267836SJohn.Forte@Sun.COM 	bcopy(lu, &ioctlViewEntry.ve_guid, sizeof (stmfGuid));
59277836SJohn.Forte@Sun.COM 
59287836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
59297836SJohn.Forte@Sun.COM 	/*
59307836SJohn.Forte@Sun.COM 	 * Issue ioctl to add to the view entry
59317836SJohn.Forte@Sun.COM 	 */
59327836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
59337836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry);
59347836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry;
59357836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_REMOVE_VIEW_ENTRY, &stmfIoctl);
59367836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
59377836SJohn.Forte@Sun.COM 		switch (errno) {
59387836SJohn.Forte@Sun.COM 			case EBUSY:
59397836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
59407836SJohn.Forte@Sun.COM 				break;
59419585STim.Szeto@Sun.COM 			case EPERM:
59429585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
59439585STim.Szeto@Sun.COM 				break;
59447836SJohn.Forte@Sun.COM 			case EACCES:
59457836SJohn.Forte@Sun.COM 				switch (stmfIoctl.stmf_error) {
59467836SJohn.Forte@Sun.COM 					case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
59477836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_CONFIG_NONE;
59487836SJohn.Forte@Sun.COM 						break;
59497836SJohn.Forte@Sun.COM 					default:
59507836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_PERM;
59517836SJohn.Forte@Sun.COM 						break;
59527836SJohn.Forte@Sun.COM 				}
59537836SJohn.Forte@Sun.COM 				break;
59547836SJohn.Forte@Sun.COM 			case ENODEV:
59557836SJohn.Forte@Sun.COM 			case ENOENT:
59567836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
59577836SJohn.Forte@Sun.COM 				break;
59587836SJohn.Forte@Sun.COM 			default:
59597836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
59607836SJohn.Forte@Sun.COM 				    "stmfRemoveViewEntry:ioctl errno(%d)",
59617836SJohn.Forte@Sun.COM 				    errno);
59627836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
59637836SJohn.Forte@Sun.COM 				break;
59647836SJohn.Forte@Sun.COM 		}
59657836SJohn.Forte@Sun.COM 		goto done;
59667836SJohn.Forte@Sun.COM 	}
59677836SJohn.Forte@Sun.COM 
59689585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
59699585STim.Szeto@Sun.COM 		goto done;
59709585STim.Szeto@Sun.COM 	}
59719585STim.Szeto@Sun.COM 
59727836SJohn.Forte@Sun.COM 	ret = psRemoveViewEntry(lu, viewEntryIndex);
59737836SJohn.Forte@Sun.COM 	switch (ret) {
59747836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
59757836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
59767836SJohn.Forte@Sun.COM 			break;
59777836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
59787836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
59797836SJohn.Forte@Sun.COM 			break;
59807836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
59817836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
59827836SJohn.Forte@Sun.COM 			break;
59837836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
59847836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
59857836SJohn.Forte@Sun.COM 			break;
59867836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
59877836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
59887836SJohn.Forte@Sun.COM 			break;
59897836SJohn.Forte@Sun.COM 		default:
59907836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
59917836SJohn.Forte@Sun.COM 			    "stmfRemoveViewEntry" "psRemoveViewEntry:error(%d)",
59927836SJohn.Forte@Sun.COM 			    ret);
59937836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
59947836SJohn.Forte@Sun.COM 			break;
59957836SJohn.Forte@Sun.COM 	}
59967836SJohn.Forte@Sun.COM 
59977836SJohn.Forte@Sun.COM done:
59987836SJohn.Forte@Sun.COM 	(void) close(fd);
59997836SJohn.Forte@Sun.COM 	return (ret);
60007836SJohn.Forte@Sun.COM }
60017836SJohn.Forte@Sun.COM 
60027836SJohn.Forte@Sun.COM /*
60037836SJohn.Forte@Sun.COM  * stmfSetProviderData
60047836SJohn.Forte@Sun.COM  *
60057836SJohn.Forte@Sun.COM  * Purpose: set the provider data
60067836SJohn.Forte@Sun.COM  *
60077836SJohn.Forte@Sun.COM  * providerName - unique name of provider
60087836SJohn.Forte@Sun.COM  * nvl - nvlist to set
60097836SJohn.Forte@Sun.COM  * providerType - type of provider for which to set data
60107836SJohn.Forte@Sun.COM  *		STMF_LU_PROVIDER_TYPE
60117836SJohn.Forte@Sun.COM  *		STMF_PORT_PROVIDER_TYPE
60127836SJohn.Forte@Sun.COM  */
60137836SJohn.Forte@Sun.COM int
60147836SJohn.Forte@Sun.COM stmfSetProviderData(char *providerName, nvlist_t *nvl, int providerType)
60157836SJohn.Forte@Sun.COM {
60167836SJohn.Forte@Sun.COM 	return (stmfSetProviderDataProt(providerName, nvl, providerType,
60177836SJohn.Forte@Sun.COM 	    NULL));
60187836SJohn.Forte@Sun.COM }
60197836SJohn.Forte@Sun.COM 
60207836SJohn.Forte@Sun.COM /*
60217836SJohn.Forte@Sun.COM  * stmfSetProviderDataProt
60227836SJohn.Forte@Sun.COM  *
60237836SJohn.Forte@Sun.COM  * Purpose: set the provider data
60247836SJohn.Forte@Sun.COM  *
60257836SJohn.Forte@Sun.COM  * providerName - unique name of provider
60267836SJohn.Forte@Sun.COM  * nvl - nvlist to set
60277836SJohn.Forte@Sun.COM  * providerType - type of provider for which to set data
60287836SJohn.Forte@Sun.COM  *		STMF_LU_PROVIDER_TYPE
60297836SJohn.Forte@Sun.COM  *		STMF_PORT_PROVIDER_TYPE
60307836SJohn.Forte@Sun.COM  * setToken - Stale data token returned in the stmfGetProviderDataProt()
60317836SJohn.Forte@Sun.COM  *	      call or NULL.
60327836SJohn.Forte@Sun.COM  */
60337836SJohn.Forte@Sun.COM int
60347836SJohn.Forte@Sun.COM stmfSetProviderDataProt(char *providerName, nvlist_t *nvl, int providerType,
60357836SJohn.Forte@Sun.COM     uint64_t *setToken)
60367836SJohn.Forte@Sun.COM {
60377836SJohn.Forte@Sun.COM 	int ret;
60387836SJohn.Forte@Sun.COM 	int fd;
60397836SJohn.Forte@Sun.COM 
60407836SJohn.Forte@Sun.COM 	if (providerName == NULL || nvl == NULL) {
60417836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
60427836SJohn.Forte@Sun.COM 	}
60437836SJohn.Forte@Sun.COM 
60447836SJohn.Forte@Sun.COM 	if (providerType != STMF_LU_PROVIDER_TYPE &&
60457836SJohn.Forte@Sun.COM 	    providerType != STMF_PORT_PROVIDER_TYPE) {
60467836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
60477836SJohn.Forte@Sun.COM 	}
60487836SJohn.Forte@Sun.COM 
60497836SJohn.Forte@Sun.COM 	/* call init */
60507836SJohn.Forte@Sun.COM 	ret = initializeConfig();
60517836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
60527836SJohn.Forte@Sun.COM 		return (ret);
60537836SJohn.Forte@Sun.COM 	}
60547836SJohn.Forte@Sun.COM 
60557836SJohn.Forte@Sun.COM 	/*
60567836SJohn.Forte@Sun.COM 	 * Open control node for stmf
60577836SJohn.Forte@Sun.COM 	 */
60587836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
60597836SJohn.Forte@Sun.COM 		return (ret);
60607836SJohn.Forte@Sun.COM 
60619585STim.Szeto@Sun.COM 	ret = setProviderData(fd, providerName, nvl, providerType, setToken);
60627836SJohn.Forte@Sun.COM 
60637836SJohn.Forte@Sun.COM 	(void) close(fd);
60647836SJohn.Forte@Sun.COM 
60657836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
60667836SJohn.Forte@Sun.COM 		goto done;
60677836SJohn.Forte@Sun.COM 	}
60687836SJohn.Forte@Sun.COM 
60699585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
60709585STim.Szeto@Sun.COM 		goto done;
60719585STim.Szeto@Sun.COM 	}
60729585STim.Szeto@Sun.COM 
60737836SJohn.Forte@Sun.COM 	/* setting driver provider data successful. Now persist it */
60749585STim.Szeto@Sun.COM 	ret = psSetProviderData(providerName, nvl, providerType, NULL);
60757836SJohn.Forte@Sun.COM 	switch (ret) {
60767836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
60777836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
60787836SJohn.Forte@Sun.COM 			break;
60797836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_EXISTS:
60807836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_EXISTS;
60817836SJohn.Forte@Sun.COM 			break;
60827836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
60837836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
60847836SJohn.Forte@Sun.COM 			break;
60857836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
60867836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
60877836SJohn.Forte@Sun.COM 			break;
60887836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
60897836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
60907836SJohn.Forte@Sun.COM 			break;
60917836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_PROV_DATA_STALE:
60927836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_PROV_DATA_STALE;
60937836SJohn.Forte@Sun.COM 			break;
60947836SJohn.Forte@Sun.COM 		default:
60957836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
60967836SJohn.Forte@Sun.COM 			    "stmfSetProviderData"
60977836SJohn.Forte@Sun.COM 			    "psSetProviderData:error(%d)", ret);
60987836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
60997836SJohn.Forte@Sun.COM 			break;
61007836SJohn.Forte@Sun.COM 	}
61017836SJohn.Forte@Sun.COM 
61027836SJohn.Forte@Sun.COM done:
61037836SJohn.Forte@Sun.COM 	return (ret);
61047836SJohn.Forte@Sun.COM }
61057836SJohn.Forte@Sun.COM 
61067836SJohn.Forte@Sun.COM /*
61079585STim.Szeto@Sun.COM  * getProviderData
61089585STim.Szeto@Sun.COM  *
61099585STim.Szeto@Sun.COM  * Purpose: set the provider data from stmf
61109585STim.Szeto@Sun.COM  *
61119585STim.Szeto@Sun.COM  * providerName - unique name of provider
61129585STim.Szeto@Sun.COM  * nvl - nvlist to load/retrieve
61139585STim.Szeto@Sun.COM  * providerType - logical unit or port provider
61149585STim.Szeto@Sun.COM  * setToken - returned stale data token
61159585STim.Szeto@Sun.COM  */
61169585STim.Szeto@Sun.COM int
61179585STim.Szeto@Sun.COM getProviderData(char *providerName, nvlist_t **nvl, int providerType,
61189585STim.Szeto@Sun.COM     uint64_t *setToken)
61199585STim.Szeto@Sun.COM {
61209585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
61219585STim.Szeto@Sun.COM 	int fd;
61229585STim.Szeto@Sun.COM 	int ioctlRet;
61239585STim.Szeto@Sun.COM 	size_t nvlistSize = ALLOC_PP_DATA_SIZE;
61249585STim.Szeto@Sun.COM 	int retryCnt = 0;
61259585STim.Szeto@Sun.COM 	int retryCntMax = MAX_PROVIDER_RETRY;
61269585STim.Szeto@Sun.COM 	stmf_ppioctl_data_t ppi = {0}, *ppi_out = NULL;
61279585STim.Szeto@Sun.COM 	boolean_t retry = B_TRUE;
61289585STim.Szeto@Sun.COM 	stmf_iocdata_t stmfIoctl;
61299585STim.Szeto@Sun.COM 
61309585STim.Szeto@Sun.COM 	if (providerName == NULL) {
61319585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
61329585STim.Szeto@Sun.COM 	}
61339585STim.Szeto@Sun.COM 
61349585STim.Szeto@Sun.COM 	/*
61359585STim.Szeto@Sun.COM 	 * Open control node for stmf
61369585STim.Szeto@Sun.COM 	 */
61379585STim.Szeto@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
61389585STim.Szeto@Sun.COM 		return (ret);
61399585STim.Szeto@Sun.COM 
61409585STim.Szeto@Sun.COM 	/* set provider name and provider type */
61419585STim.Szeto@Sun.COM 	if (strlcpy(ppi.ppi_name, providerName,
61429585STim.Szeto@Sun.COM 	    sizeof (ppi.ppi_name)) >=
61439585STim.Szeto@Sun.COM 	    sizeof (ppi.ppi_name)) {
61449585STim.Szeto@Sun.COM 		ret = STMF_ERROR_INVALID_ARG;
61459585STim.Szeto@Sun.COM 		goto done;
61469585STim.Szeto@Sun.COM 	}
61479585STim.Szeto@Sun.COM 	switch (providerType) {
61489585STim.Szeto@Sun.COM 		case STMF_LU_PROVIDER_TYPE:
61499585STim.Szeto@Sun.COM 			ppi.ppi_lu_provider = 1;
61509585STim.Szeto@Sun.COM 			break;
61519585STim.Szeto@Sun.COM 		case STMF_PORT_PROVIDER_TYPE:
61529585STim.Szeto@Sun.COM 			ppi.ppi_port_provider = 1;
61539585STim.Szeto@Sun.COM 			break;
61549585STim.Szeto@Sun.COM 		default:
61559585STim.Szeto@Sun.COM 			ret = STMF_ERROR_INVALID_ARG;
61569585STim.Szeto@Sun.COM 			goto done;
61579585STim.Szeto@Sun.COM 	}
61589585STim.Szeto@Sun.COM 
61599585STim.Szeto@Sun.COM 	do {
61609585STim.Szeto@Sun.COM 		/* allocate memory for ioctl */
61619585STim.Szeto@Sun.COM 		ppi_out = (stmf_ppioctl_data_t *)calloc(1, nvlistSize +
61629585STim.Szeto@Sun.COM 		    sizeof (stmf_ppioctl_data_t));
61639585STim.Szeto@Sun.COM 		if (ppi_out == NULL) {
61649585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NOMEM;
61659585STim.Szeto@Sun.COM 			goto done;
61669585STim.Szeto@Sun.COM 
61679585STim.Szeto@Sun.COM 		}
61689585STim.Szeto@Sun.COM 
61699585STim.Szeto@Sun.COM 		/* set the size of the ioctl data to allocated buffer */
61709585STim.Szeto@Sun.COM 		ppi.ppi_data_size = nvlistSize;
61719585STim.Szeto@Sun.COM 
61729585STim.Szeto@Sun.COM 		bzero(&stmfIoctl, sizeof (stmfIoctl));
61739585STim.Szeto@Sun.COM 
61749585STim.Szeto@Sun.COM 		stmfIoctl.stmf_version = STMF_VERSION_1;
61759585STim.Szeto@Sun.COM 		stmfIoctl.stmf_ibuf_size = sizeof (stmf_ppioctl_data_t);
61769585STim.Szeto@Sun.COM 		stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ppi;
61779585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf_size = sizeof (stmf_ppioctl_data_t) +
61789585STim.Szeto@Sun.COM 		    nvlistSize;
61799585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)ppi_out;
61809585STim.Szeto@Sun.COM 		ioctlRet = ioctl(fd, STMF_IOCTL_GET_PP_DATA, &stmfIoctl);
61819585STim.Szeto@Sun.COM 		if (ioctlRet != 0) {
61829585STim.Szeto@Sun.COM 			switch (errno) {
61839585STim.Szeto@Sun.COM 				case EBUSY:
61849585STim.Szeto@Sun.COM 					ret = STMF_ERROR_BUSY;
61859585STim.Szeto@Sun.COM 					break;
61869585STim.Szeto@Sun.COM 				case EPERM:
61879585STim.Szeto@Sun.COM 				case EACCES:
61889585STim.Szeto@Sun.COM 					ret = STMF_ERROR_PERM;
61899585STim.Szeto@Sun.COM 					break;
61909585STim.Szeto@Sun.COM 				case EINVAL:
61919585STim.Szeto@Sun.COM 					if (stmfIoctl.stmf_error ==
61929585STim.Szeto@Sun.COM 					    STMF_IOCERR_INSUFFICIENT_BUF) {
61939585STim.Szeto@Sun.COM 						nvlistSize =
61949585STim.Szeto@Sun.COM 						    ppi_out->ppi_data_size;
61959585STim.Szeto@Sun.COM 						free(ppi_out);
61969585STim.Szeto@Sun.COM 						ppi_out = NULL;
61979585STim.Szeto@Sun.COM 						if (retryCnt++ > retryCntMax) {
61989585STim.Szeto@Sun.COM 							retry = B_FALSE;
61999585STim.Szeto@Sun.COM 							ret = STMF_ERROR_BUSY;
62009585STim.Szeto@Sun.COM 						} else {
62019585STim.Szeto@Sun.COM 							ret =
62029585STim.Szeto@Sun.COM 							    STMF_STATUS_SUCCESS;
62039585STim.Szeto@Sun.COM 						}
62049585STim.Szeto@Sun.COM 					} else {
62059585STim.Szeto@Sun.COM 						syslog(LOG_DEBUG,
62069585STim.Szeto@Sun.COM 						    "getProviderData:ioctl"
62079585STim.Szeto@Sun.COM 						    "unable to retrieve "
62089585STim.Szeto@Sun.COM 						    "nvlist");
62099585STim.Szeto@Sun.COM 						ret = STMF_STATUS_ERROR;
62109585STim.Szeto@Sun.COM 					}
62119585STim.Szeto@Sun.COM 					break;
62129585STim.Szeto@Sun.COM 				case ENOENT:
62139585STim.Szeto@Sun.COM 					ret = STMF_ERROR_NOT_FOUND;
62149585STim.Szeto@Sun.COM 					break;
62159585STim.Szeto@Sun.COM 				default:
62169585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
62179585STim.Szeto@Sun.COM 					    "getProviderData:ioctl errno(%d)",
62189585STim.Szeto@Sun.COM 					    errno);
62199585STim.Szeto@Sun.COM 					ret = STMF_STATUS_ERROR;
62209585STim.Szeto@Sun.COM 					break;
62219585STim.Szeto@Sun.COM 			}
62229585STim.Szeto@Sun.COM 			if (ret != STMF_STATUS_SUCCESS)
62239585STim.Szeto@Sun.COM 				goto done;
62249585STim.Szeto@Sun.COM 		}
62259585STim.Szeto@Sun.COM 	} while (retry && stmfIoctl.stmf_error == STMF_IOCERR_INSUFFICIENT_BUF);
62269585STim.Szeto@Sun.COM 
62279585STim.Szeto@Sun.COM 	if ((ret = nvlist_unpack((char *)ppi_out->ppi_data,
62289585STim.Szeto@Sun.COM 	    ppi_out->ppi_data_size, nvl, 0)) != 0) {
62299585STim.Szeto@Sun.COM 		ret = STMF_STATUS_ERROR;
62309585STim.Szeto@Sun.COM 		goto done;
62319585STim.Szeto@Sun.COM 	}
62329585STim.Szeto@Sun.COM 
62339585STim.Szeto@Sun.COM 	/* caller has asked for new token */
62349585STim.Szeto@Sun.COM 	if (setToken) {
62359585STim.Szeto@Sun.COM 		*setToken = ppi_out->ppi_token;
62369585STim.Szeto@Sun.COM 	}
62379585STim.Szeto@Sun.COM done:
62389585STim.Szeto@Sun.COM 	free(ppi_out);
62399585STim.Szeto@Sun.COM 	(void) close(fd);
62409585STim.Szeto@Sun.COM 	return (ret);
62419585STim.Szeto@Sun.COM }
62429585STim.Szeto@Sun.COM 
62439585STim.Szeto@Sun.COM /*
62447836SJohn.Forte@Sun.COM  * setProviderData
62457836SJohn.Forte@Sun.COM  *
62469585STim.Szeto@Sun.COM  * Purpose: set the provider data in stmf
62477836SJohn.Forte@Sun.COM  *
62487836SJohn.Forte@Sun.COM  * providerName - unique name of provider
62497836SJohn.Forte@Sun.COM  * nvl - nvlist to set
62507836SJohn.Forte@Sun.COM  * providerType - logical unit or port provider
62519585STim.Szeto@Sun.COM  * setToken - stale data token to check if not NULL
62527836SJohn.Forte@Sun.COM  */
62537836SJohn.Forte@Sun.COM static int
62549585STim.Szeto@Sun.COM setProviderData(int fd, char *providerName, nvlist_t *nvl, int providerType,
62559585STim.Szeto@Sun.COM     uint64_t *setToken)
62567836SJohn.Forte@Sun.COM {
62577836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
62587836SJohn.Forte@Sun.COM 	int ioctlRet;
62597836SJohn.Forte@Sun.COM 	size_t nvlistEncodedSize;
62607836SJohn.Forte@Sun.COM 	stmf_ppioctl_data_t *ppi = NULL;
62619585STim.Szeto@Sun.COM 	uint64_t outToken;
62627836SJohn.Forte@Sun.COM 	char *allocatedNvBuffer;
62637836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
62647836SJohn.Forte@Sun.COM 
62657836SJohn.Forte@Sun.COM 	if (providerName == NULL) {
62667836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
62677836SJohn.Forte@Sun.COM 	}
62687836SJohn.Forte@Sun.COM 
62697836SJohn.Forte@Sun.COM 	/* get size of encoded nvlist */
62707836SJohn.Forte@Sun.COM 	if (nvlist_size(nvl, &nvlistEncodedSize, NV_ENCODE_XDR) != 0) {
62717836SJohn.Forte@Sun.COM 		return (STMF_STATUS_ERROR);
62727836SJohn.Forte@Sun.COM 	}
62737836SJohn.Forte@Sun.COM 
62747836SJohn.Forte@Sun.COM 	/* allocate memory for ioctl */
62757836SJohn.Forte@Sun.COM 	ppi = (stmf_ppioctl_data_t *)calloc(1, nvlistEncodedSize +
62767836SJohn.Forte@Sun.COM 	    sizeof (stmf_ppioctl_data_t));
62777836SJohn.Forte@Sun.COM 	if (ppi == NULL) {
62787836SJohn.Forte@Sun.COM 		return (STMF_ERROR_NOMEM);
62797836SJohn.Forte@Sun.COM 	}
62807836SJohn.Forte@Sun.COM 
62819585STim.Szeto@Sun.COM 	if (setToken) {
62829585STim.Szeto@Sun.COM 		ppi->ppi_token_valid = 1;
62839585STim.Szeto@Sun.COM 		ppi->ppi_token = *setToken;
62849585STim.Szeto@Sun.COM 	}
62859585STim.Szeto@Sun.COM 
62867836SJohn.Forte@Sun.COM 	allocatedNvBuffer = (char *)&ppi->ppi_data;
62877836SJohn.Forte@Sun.COM 	if (nvlist_pack(nvl, &allocatedNvBuffer, &nvlistEncodedSize,
62887836SJohn.Forte@Sun.COM 	    NV_ENCODE_XDR, 0) != 0) {
62897836SJohn.Forte@Sun.COM 		return (STMF_STATUS_ERROR);
62907836SJohn.Forte@Sun.COM 	}
62917836SJohn.Forte@Sun.COM 
62927836SJohn.Forte@Sun.COM 	/* set provider name and provider type */
62937836SJohn.Forte@Sun.COM 	(void) strncpy(ppi->ppi_name, providerName, sizeof (ppi->ppi_name));
62947836SJohn.Forte@Sun.COM 	switch (providerType) {
62957836SJohn.Forte@Sun.COM 		case STMF_LU_PROVIDER_TYPE:
62967836SJohn.Forte@Sun.COM 			ppi->ppi_lu_provider = 1;
62977836SJohn.Forte@Sun.COM 			break;
62987836SJohn.Forte@Sun.COM 		case STMF_PORT_PROVIDER_TYPE:
62997836SJohn.Forte@Sun.COM 			ppi->ppi_port_provider = 1;
63007836SJohn.Forte@Sun.COM 			break;
63017836SJohn.Forte@Sun.COM 		default:
63027836SJohn.Forte@Sun.COM 			return (STMF_ERROR_INVALID_ARG);
63037836SJohn.Forte@Sun.COM 	}
63047836SJohn.Forte@Sun.COM 
63057836SJohn.Forte@Sun.COM 	/* set the size of the ioctl data to packed data size */
63067836SJohn.Forte@Sun.COM 	ppi->ppi_data_size = nvlistEncodedSize;
63077836SJohn.Forte@Sun.COM 
63087836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
63097836SJohn.Forte@Sun.COM 
63107836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
63117836SJohn.Forte@Sun.COM 	/*
63127836SJohn.Forte@Sun.COM 	 * Subtracting 8 from the size as that is the size of the last member
63137836SJohn.Forte@Sun.COM 	 * of the structure where the packed data resides
63147836SJohn.Forte@Sun.COM 	 */
63157836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = nvlistEncodedSize +
63167836SJohn.Forte@Sun.COM 	    sizeof (stmf_ppioctl_data_t) - 8;
63177836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)ppi;
63189585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf_size = sizeof (uint64_t);
63199585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&outToken;
63207836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_LOAD_PP_DATA, &stmfIoctl);
63217836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
63227836SJohn.Forte@Sun.COM 		switch (errno) {
63237836SJohn.Forte@Sun.COM 			case EBUSY:
63247836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
63257836SJohn.Forte@Sun.COM 				break;
63269585STim.Szeto@Sun.COM 			case EPERM:
63277836SJohn.Forte@Sun.COM 			case EACCES:
63287836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
63297836SJohn.Forte@Sun.COM 				break;
63309585STim.Szeto@Sun.COM 			case EINVAL:
63319585STim.Szeto@Sun.COM 				if (stmfIoctl.stmf_error ==
63329585STim.Szeto@Sun.COM 				    STMF_IOCERR_PPD_UPDATED) {
63339585STim.Szeto@Sun.COM 					ret = STMF_ERROR_PROV_DATA_STALE;
63349585STim.Szeto@Sun.COM 				} else {
63359585STim.Szeto@Sun.COM 					ret = STMF_STATUS_ERROR;
63369585STim.Szeto@Sun.COM 				}
63379585STim.Szeto@Sun.COM 				break;
63387836SJohn.Forte@Sun.COM 			default:
63397836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
63407836SJohn.Forte@Sun.COM 				    "setProviderData:ioctl errno(%d)", errno);
63417836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
63427836SJohn.Forte@Sun.COM 				break;
63437836SJohn.Forte@Sun.COM 		}
63447836SJohn.Forte@Sun.COM 		if (ret != STMF_STATUS_SUCCESS)
63457836SJohn.Forte@Sun.COM 			goto done;
63467836SJohn.Forte@Sun.COM 	}
63477836SJohn.Forte@Sun.COM 
63489585STim.Szeto@Sun.COM 	/* caller has asked for new token */
63499585STim.Szeto@Sun.COM 	if (setToken) {
63509585STim.Szeto@Sun.COM 		*setToken = outToken;
63519585STim.Szeto@Sun.COM 	}
63527836SJohn.Forte@Sun.COM done:
63537836SJohn.Forte@Sun.COM 	free(ppi);
63547836SJohn.Forte@Sun.COM 	return (ret);
63557836SJohn.Forte@Sun.COM }
63569585STim.Szeto@Sun.COM 
63579585STim.Szeto@Sun.COM /*
63589585STim.Szeto@Sun.COM  * set the persistence method in the library only or library and service
63599585STim.Szeto@Sun.COM  */
63609585STim.Szeto@Sun.COM int
63619585STim.Szeto@Sun.COM stmfSetPersistMethod(uint8_t persistType, boolean_t serviceSet)
63629585STim.Szeto@Sun.COM {
63639585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
63649585STim.Szeto@Sun.COM 	int oldPersist;
63659585STim.Szeto@Sun.COM 
63669585STim.Szeto@Sun.COM 	(void) pthread_mutex_lock(&persistenceTypeLock);
63679585STim.Szeto@Sun.COM 	oldPersist = iPersistType;
63689585STim.Szeto@Sun.COM 	if (persistType == STMF_PERSIST_NONE ||
63699585STim.Szeto@Sun.COM 	    persistType == STMF_PERSIST_SMF) {
63709585STim.Szeto@Sun.COM 		iLibSetPersist = B_TRUE;
63719585STim.Szeto@Sun.COM 		iPersistType = persistType;
63729585STim.Szeto@Sun.COM 	} else {
63739585STim.Szeto@Sun.COM 		(void) pthread_mutex_unlock(&persistenceTypeLock);
63749585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
63759585STim.Szeto@Sun.COM 	}
63769585STim.Szeto@Sun.COM 	/* Is this for this library open or in SMF */
63779585STim.Szeto@Sun.COM 	if (serviceSet == B_TRUE) {
63789585STim.Szeto@Sun.COM 		ret = psSetServicePersist(persistType);
63799585STim.Szeto@Sun.COM 		if (ret != STMF_PS_SUCCESS) {
63809585STim.Szeto@Sun.COM 			ret = STMF_ERROR_PERSIST_TYPE;
63819585STim.Szeto@Sun.COM 			/* Set to old value */
63829585STim.Szeto@Sun.COM 			iPersistType = oldPersist;
63839585STim.Szeto@Sun.COM 		}
63849585STim.Szeto@Sun.COM 	}
63859585STim.Szeto@Sun.COM 	(void) pthread_mutex_unlock(&persistenceTypeLock);
63869585STim.Szeto@Sun.COM 
63879585STim.Szeto@Sun.COM 	return (ret);
63889585STim.Szeto@Sun.COM }
63899585STim.Szeto@Sun.COM 
63909585STim.Szeto@Sun.COM /*
63919585STim.Szeto@Sun.COM  * Only returns internal state for persist. If unset, goes to ps. If that
63929585STim.Szeto@Sun.COM  * fails, returns default setting
63939585STim.Szeto@Sun.COM  */
63949585STim.Szeto@Sun.COM static uint8_t
63959585STim.Szeto@Sun.COM iGetPersistMethod()
63969585STim.Szeto@Sun.COM {
63979585STim.Szeto@Sun.COM 
63989585STim.Szeto@Sun.COM 	uint8_t persistType = 0;
63999585STim.Szeto@Sun.COM 
64009585STim.Szeto@Sun.COM 	(void) pthread_mutex_lock(&persistenceTypeLock);
64019585STim.Szeto@Sun.COM 	if (iLibSetPersist) {
64029585STim.Szeto@Sun.COM 		persistType = iPersistType;
64039585STim.Szeto@Sun.COM 	} else {
64049585STim.Szeto@Sun.COM 		int ret;
64059585STim.Szeto@Sun.COM 		ret = psGetServicePersist(&persistType);
64069585STim.Szeto@Sun.COM 		if (ret != STMF_PS_SUCCESS) {
64079585STim.Szeto@Sun.COM 			/* set to default */
64089585STim.Szeto@Sun.COM 			persistType = STMF_DEFAULT_PERSIST;
64099585STim.Szeto@Sun.COM 		}
64109585STim.Szeto@Sun.COM 	}
64119585STim.Szeto@Sun.COM 	(void) pthread_mutex_unlock(&persistenceTypeLock);
64129585STim.Szeto@Sun.COM 	return (persistType);
64139585STim.Szeto@Sun.COM }
64149585STim.Szeto@Sun.COM 
64159585STim.Szeto@Sun.COM /*
64169585STim.Szeto@Sun.COM  * Returns either library state or persistent config state depending on
64179585STim.Szeto@Sun.COM  * serviceState
64189585STim.Szeto@Sun.COM  */
64199585STim.Szeto@Sun.COM int
64209585STim.Szeto@Sun.COM stmfGetPersistMethod(uint8_t *persistType, boolean_t serviceState)
64219585STim.Szeto@Sun.COM {
64229585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
64239585STim.Szeto@Sun.COM 
64249585STim.Szeto@Sun.COM 	if (persistType == NULL) {
64259585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
64269585STim.Szeto@Sun.COM 	}
64279585STim.Szeto@Sun.COM 	if (serviceState) {
64289585STim.Szeto@Sun.COM 		ret = psGetServicePersist(persistType);
64299585STim.Szeto@Sun.COM 		if (ret != STMF_PS_SUCCESS) {
64309585STim.Szeto@Sun.COM 			ret = STMF_ERROR_PERSIST_TYPE;
64319585STim.Szeto@Sun.COM 		}
64329585STim.Szeto@Sun.COM 	} else {
64339585STim.Szeto@Sun.COM 		(void) pthread_mutex_lock(&persistenceTypeLock);
64349585STim.Szeto@Sun.COM 		if (iLibSetPersist) {
64359585STim.Szeto@Sun.COM 			*persistType = iPersistType;
64369585STim.Szeto@Sun.COM 		} else {
64379585STim.Szeto@Sun.COM 			*persistType = STMF_DEFAULT_PERSIST;
64389585STim.Szeto@Sun.COM 		}
64399585STim.Szeto@Sun.COM 		(void) pthread_mutex_unlock(&persistenceTypeLock);
64409585STim.Szeto@Sun.COM 	}
64419585STim.Szeto@Sun.COM 
64429585STim.Szeto@Sun.COM 	return (ret);
64439585STim.Szeto@Sun.COM }
644410691STim.Szeto@Sun.COM 
644510691STim.Szeto@Sun.COM /*
644610725SJohn.Forte@Sun.COM  * stmfPostProxyMsg
644710725SJohn.Forte@Sun.COM  *
644810725SJohn.Forte@Sun.COM  * Purpose: Post a message to the proxy port provider
644910725SJohn.Forte@Sun.COM  *
645010725SJohn.Forte@Sun.COM  * buf - buffer containing message to post
645110725SJohn.Forte@Sun.COM  * buflen - buffer length
645210725SJohn.Forte@Sun.COM  */
645310725SJohn.Forte@Sun.COM int
645410725SJohn.Forte@Sun.COM stmfPostProxyMsg(int hdl, void *buf, uint32_t buflen)
645510725SJohn.Forte@Sun.COM {
645610725SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
645710725SJohn.Forte@Sun.COM 	int ioctlRet;
645810725SJohn.Forte@Sun.COM 	pppt_iocdata_t ppptIoctl = {0};
645910725SJohn.Forte@Sun.COM 
646010725SJohn.Forte@Sun.COM 	if (buf == NULL) {
646110725SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
646210725SJohn.Forte@Sun.COM 	}
646310725SJohn.Forte@Sun.COM 
646410725SJohn.Forte@Sun.COM 	/*
646510725SJohn.Forte@Sun.COM 	 * Issue ioctl to post the message
646610725SJohn.Forte@Sun.COM 	 */
646710725SJohn.Forte@Sun.COM 	ppptIoctl.pppt_version = PPPT_VERSION_1;
646810725SJohn.Forte@Sun.COM 	ppptIoctl.pppt_buf_size = buflen;
646910725SJohn.Forte@Sun.COM 	ppptIoctl.pppt_buf = (uint64_t)(unsigned long)buf;
647010725SJohn.Forte@Sun.COM 	ioctlRet = ioctl(hdl, PPPT_MESSAGE, &ppptIoctl);
647110725SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
647210725SJohn.Forte@Sun.COM 		switch (errno) {
647310725SJohn.Forte@Sun.COM 			case EPERM:
647410725SJohn.Forte@Sun.COM 			case EACCES:
647510725SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
647610725SJohn.Forte@Sun.COM 				break;
647710725SJohn.Forte@Sun.COM 			default:
647810725SJohn.Forte@Sun.COM 				ret = STMF_ERROR_POST_MSG_FAILED;
647910725SJohn.Forte@Sun.COM 				break;
648010725SJohn.Forte@Sun.COM 		}
648110725SJohn.Forte@Sun.COM 	}
648210725SJohn.Forte@Sun.COM 
648310725SJohn.Forte@Sun.COM 	return (ret);
648410725SJohn.Forte@Sun.COM }
648510725SJohn.Forte@Sun.COM 
648610725SJohn.Forte@Sun.COM /*
648710725SJohn.Forte@Sun.COM  * stmfInitProxyDoor
648810725SJohn.Forte@Sun.COM  *
648910725SJohn.Forte@Sun.COM  * Purpose: Install door in proxy
649010725SJohn.Forte@Sun.COM  *
649110725SJohn.Forte@Sun.COM  * hdl - pointer to returned handle
649210725SJohn.Forte@Sun.COM  * fd - door from door_create()
649310725SJohn.Forte@Sun.COM  */
649410725SJohn.Forte@Sun.COM int
649510725SJohn.Forte@Sun.COM stmfInitProxyDoor(int *hdl, int door)
649610725SJohn.Forte@Sun.COM {
649710725SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
649810725SJohn.Forte@Sun.COM 	int ioctlRet;
649910725SJohn.Forte@Sun.COM 	int fd;
650010725SJohn.Forte@Sun.COM 	pppt_iocdata_t ppptIoctl = {0};
650110725SJohn.Forte@Sun.COM 
650210725SJohn.Forte@Sun.COM 	if (hdl == NULL) {
650310725SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
650410725SJohn.Forte@Sun.COM 	}
650510725SJohn.Forte@Sun.COM 
650610725SJohn.Forte@Sun.COM 	/*
650710725SJohn.Forte@Sun.COM 	 * Open control node for pppt
650810725SJohn.Forte@Sun.COM 	 */
650910725SJohn.Forte@Sun.COM 	if ((ret = openPppt(OPEN_PPPT, &fd)) != STMF_STATUS_SUCCESS) {
651010725SJohn.Forte@Sun.COM 		return (ret);
651110725SJohn.Forte@Sun.COM 	}
651210725SJohn.Forte@Sun.COM 
651310725SJohn.Forte@Sun.COM 	/*
651410725SJohn.Forte@Sun.COM 	 * Issue ioctl to install the door
651510725SJohn.Forte@Sun.COM 	 */
651610725SJohn.Forte@Sun.COM 	ppptIoctl.pppt_version = PPPT_VERSION_1;
651710725SJohn.Forte@Sun.COM 	ppptIoctl.pppt_door_fd = (uint32_t)door;
651810725SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, PPPT_INSTALL_DOOR, &ppptIoctl);
651910725SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
652010725SJohn.Forte@Sun.COM 		switch (errno) {
652110725SJohn.Forte@Sun.COM 			case EPERM:
652210725SJohn.Forte@Sun.COM 			case EACCES:
652310725SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
652410725SJohn.Forte@Sun.COM 				break;
652510725SJohn.Forte@Sun.COM 			case EINVAL:
652610725SJohn.Forte@Sun.COM 				ret = STMF_ERROR_INVALID_ARG;
652710725SJohn.Forte@Sun.COM 				break;
652810725SJohn.Forte@Sun.COM 			case EBUSY:
652910725SJohn.Forte@Sun.COM 				ret = STMF_ERROR_DOOR_INSTALLED;
653010725SJohn.Forte@Sun.COM 				break;
653110725SJohn.Forte@Sun.COM 			default:
653210725SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
653310725SJohn.Forte@Sun.COM 				break;
653410725SJohn.Forte@Sun.COM 		}
653510725SJohn.Forte@Sun.COM 	}
653610725SJohn.Forte@Sun.COM 
653710725SJohn.Forte@Sun.COM 	/* return driver fd to caller */
653810725SJohn.Forte@Sun.COM 	*hdl = fd;
653910725SJohn.Forte@Sun.COM 	return (ret);
654010725SJohn.Forte@Sun.COM }
654110725SJohn.Forte@Sun.COM 
654210725SJohn.Forte@Sun.COM void
654310725SJohn.Forte@Sun.COM stmfDestroyProxyDoor(int hdl)
654410725SJohn.Forte@Sun.COM {
654510725SJohn.Forte@Sun.COM 	(void) close(hdl);
654610725SJohn.Forte@Sun.COM }
654710725SJohn.Forte@Sun.COM 
654810725SJohn.Forte@Sun.COM /*
654910691STim.Szeto@Sun.COM  * validateLunNumIoctl
655010691STim.Szeto@Sun.COM  *
655110691STim.Szeto@Sun.COM  * Purpose: Issues ioctl to check and get available lun# in view entry
655210691STim.Szeto@Sun.COM  *
655310691STim.Szeto@Sun.COM  * viewEntry - view entry to use
655410691STim.Szeto@Sun.COM  */
655510691STim.Szeto@Sun.COM static int
655610691STim.Szeto@Sun.COM validateLunNumIoctl(int fd, stmfViewEntry *viewEntry)
655710691STim.Szeto@Sun.COM {
655810691STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
655910691STim.Szeto@Sun.COM 	int ioctlRet;
656010691STim.Szeto@Sun.COM 	stmf_iocdata_t stmfIoctl;
656110691STim.Szeto@Sun.COM 	stmf_view_op_entry_t ioctlViewEntry;
656210691STim.Szeto@Sun.COM 
656310691STim.Szeto@Sun.COM 	bzero(&ioctlViewEntry, sizeof (ioctlViewEntry));
656410691STim.Szeto@Sun.COM 	/*
656510691STim.Szeto@Sun.COM 	 * don't set ve_ndx or ve_ndx_valid as ve_ndx_valid should be
656610691STim.Szeto@Sun.COM 	 * false on input
656710691STim.Szeto@Sun.COM 	 */
656810691STim.Szeto@Sun.COM 	ioctlViewEntry.ve_lu_number_valid = viewEntry->luNbrValid;
656910691STim.Szeto@Sun.COM 	ioctlViewEntry.ve_all_hosts = viewEntry->allHosts;
657010691STim.Szeto@Sun.COM 	ioctlViewEntry.ve_all_targets = viewEntry->allTargets;
657110691STim.Szeto@Sun.COM 
657210691STim.Szeto@Sun.COM 	if (viewEntry->allHosts == B_FALSE) {
657310691STim.Szeto@Sun.COM 		bcopy(viewEntry->hostGroup, &ioctlViewEntry.ve_host_group.name,
657410691STim.Szeto@Sun.COM 		    sizeof (stmfGroupName));
657510691STim.Szeto@Sun.COM 		ioctlViewEntry.ve_host_group.name_size =
657610691STim.Szeto@Sun.COM 		    strlen((char *)viewEntry->hostGroup);
657710691STim.Szeto@Sun.COM 	}
657810691STim.Szeto@Sun.COM 	if (viewEntry->allTargets == B_FALSE) {
657910691STim.Szeto@Sun.COM 		bcopy(viewEntry->targetGroup,
658010691STim.Szeto@Sun.COM 		    &ioctlViewEntry.ve_target_group.name,
658110691STim.Szeto@Sun.COM 		    sizeof (stmfGroupName));
658210691STim.Szeto@Sun.COM 		ioctlViewEntry.ve_target_group.name_size =
658310691STim.Szeto@Sun.COM 		    strlen((char *)viewEntry->targetGroup);
658410691STim.Szeto@Sun.COM 	}
658510691STim.Szeto@Sun.COM 	/* Validating the lun number */
658610691STim.Szeto@Sun.COM 	if (viewEntry->luNbrValid) {
658710691STim.Szeto@Sun.COM 		bcopy(viewEntry->luNbr, &ioctlViewEntry.ve_lu_nbr,
658810691STim.Szeto@Sun.COM 		    sizeof (ioctlViewEntry.ve_lu_nbr));
658910691STim.Szeto@Sun.COM 	}
659010691STim.Szeto@Sun.COM 
659110691STim.Szeto@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
659210691STim.Szeto@Sun.COM 	/*
659310691STim.Szeto@Sun.COM 	 * Issue ioctl to validate lun# in the view entry
659410691STim.Szeto@Sun.COM 	 */
659510691STim.Szeto@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
659610691STim.Szeto@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry);
659710691STim.Szeto@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry;
659810691STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf_size = sizeof (ioctlViewEntry);
659910691STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&ioctlViewEntry;
660010691STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_VALIDATE_VIEW, &stmfIoctl);
660110691STim.Szeto@Sun.COM 
660210691STim.Szeto@Sun.COM 	/* save available lun number */
660310691STim.Szeto@Sun.COM 	if (!viewEntry->luNbrValid) {
660410691STim.Szeto@Sun.COM 		bcopy(ioctlViewEntry.ve_lu_nbr, viewEntry->luNbr,
660510691STim.Szeto@Sun.COM 		    sizeof (ioctlViewEntry.ve_lu_nbr));
660610691STim.Szeto@Sun.COM 	}
660710691STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
660810691STim.Szeto@Sun.COM 		switch (errno) {
660910691STim.Szeto@Sun.COM 			case EBUSY:
661010691STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
661110691STim.Szeto@Sun.COM 				break;
661210691STim.Szeto@Sun.COM 			case EPERM:
661310691STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
661410691STim.Szeto@Sun.COM 				break;
661510691STim.Szeto@Sun.COM 			case EACCES:
661610691STim.Szeto@Sun.COM 				switch (stmfIoctl.stmf_error) {
661710691STim.Szeto@Sun.COM 					case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
661810691STim.Szeto@Sun.COM 						ret = STMF_ERROR_CONFIG_NONE;
661910691STim.Szeto@Sun.COM 						break;
662010691STim.Szeto@Sun.COM 					default:
662110691STim.Szeto@Sun.COM 						ret = STMF_ERROR_PERM;
662210691STim.Szeto@Sun.COM 						break;
662310691STim.Szeto@Sun.COM 				}
662410691STim.Szeto@Sun.COM 				break;
662510691STim.Szeto@Sun.COM 			default:
662610691STim.Szeto@Sun.COM 				switch (stmfIoctl.stmf_error) {
662710691STim.Szeto@Sun.COM 					case STMF_IOCERR_LU_NUMBER_IN_USE:
662810691STim.Szeto@Sun.COM 						ret = STMF_ERROR_LUN_IN_USE;
662910691STim.Szeto@Sun.COM 						break;
663010691STim.Szeto@Sun.COM 					case STMF_IOCERR_VIEW_ENTRY_CONFLICT:
663110691STim.Szeto@Sun.COM 						ret = STMF_ERROR_VE_CONFLICT;
663210691STim.Szeto@Sun.COM 						break;
663310691STim.Szeto@Sun.COM 					case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
663410691STim.Szeto@Sun.COM 						ret = STMF_ERROR_CONFIG_NONE;
663510691STim.Szeto@Sun.COM 						break;
663610691STim.Szeto@Sun.COM 					case STMF_IOCERR_INVALID_HG:
663710691STim.Szeto@Sun.COM 						ret = STMF_ERROR_INVALID_HG;
663810691STim.Szeto@Sun.COM 						break;
663910691STim.Szeto@Sun.COM 					case STMF_IOCERR_INVALID_TG:
664010691STim.Szeto@Sun.COM 						ret = STMF_ERROR_INVALID_TG;
664110691STim.Szeto@Sun.COM 						break;
664210691STim.Szeto@Sun.COM 					default:
664310691STim.Szeto@Sun.COM 						syslog(LOG_DEBUG,
664410691STim.Szeto@Sun.COM 						    "addViewEntryIoctl"
664510691STim.Szeto@Sun.COM 						    ":error(%d)",
664610691STim.Szeto@Sun.COM 						    stmfIoctl.stmf_error);
664710691STim.Szeto@Sun.COM 						ret = STMF_STATUS_ERROR;
664810691STim.Szeto@Sun.COM 						break;
664910691STim.Szeto@Sun.COM 				}
665010691STim.Szeto@Sun.COM 				break;
665110691STim.Szeto@Sun.COM 		}
665210691STim.Szeto@Sun.COM 	}
665310691STim.Szeto@Sun.COM 	return (ret);
665410691STim.Szeto@Sun.COM }
665510691STim.Szeto@Sun.COM 
665610691STim.Szeto@Sun.COM /*
665710691STim.Szeto@Sun.COM  * stmfValidateView
665810691STim.Szeto@Sun.COM  *
665910691STim.Szeto@Sun.COM  * Purpose: Validate or get lun # base on TG, HG of view entry
666010691STim.Szeto@Sun.COM  *
666110691STim.Szeto@Sun.COM  * viewEntry - view entry structure to use
666210691STim.Szeto@Sun.COM  */
666310691STim.Szeto@Sun.COM int
666410691STim.Szeto@Sun.COM stmfValidateView(stmfViewEntry *viewEntry)
666510691STim.Szeto@Sun.COM {
666610691STim.Szeto@Sun.COM 	int ret;
666710691STim.Szeto@Sun.COM 	int fd;
666810691STim.Szeto@Sun.COM 	stmfViewEntry iViewEntry;
666910691STim.Szeto@Sun.COM 
667010691STim.Szeto@Sun.COM 	if (viewEntry == NULL) {
667110691STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
667210691STim.Szeto@Sun.COM 	}
667310691STim.Szeto@Sun.COM 
667410691STim.Szeto@Sun.COM 	/* initialize and set internal view entry */
667510691STim.Szeto@Sun.COM 	bzero(&iViewEntry, sizeof (iViewEntry));
667610691STim.Szeto@Sun.COM 
667710691STim.Szeto@Sun.COM 	if (!viewEntry->allHosts) {
667810691STim.Szeto@Sun.COM 		bcopy(viewEntry->hostGroup, iViewEntry.hostGroup,
667910691STim.Szeto@Sun.COM 		    sizeof (iViewEntry.hostGroup));
668010691STim.Szeto@Sun.COM 	} else {
668110691STim.Szeto@Sun.COM 		iViewEntry.allHosts = B_TRUE;
668210691STim.Szeto@Sun.COM 	}
668310691STim.Szeto@Sun.COM 
668410691STim.Szeto@Sun.COM 	if (!viewEntry->allTargets) {
668510691STim.Szeto@Sun.COM 		bcopy(viewEntry->targetGroup, iViewEntry.targetGroup,
668610691STim.Szeto@Sun.COM 		    sizeof (iViewEntry.targetGroup));
668710691STim.Szeto@Sun.COM 	} else {
668810691STim.Szeto@Sun.COM 		iViewEntry.allTargets = B_TRUE;
668910691STim.Szeto@Sun.COM 	}
669010691STim.Szeto@Sun.COM 
669110691STim.Szeto@Sun.COM 	if (viewEntry->luNbrValid) {
669210691STim.Szeto@Sun.COM 		iViewEntry.luNbrValid = B_TRUE;
669310691STim.Szeto@Sun.COM 		bcopy(viewEntry->luNbr, iViewEntry.luNbr,
669410691STim.Szeto@Sun.COM 		    sizeof (iViewEntry.luNbr));
669510691STim.Szeto@Sun.COM 	}
669610691STim.Szeto@Sun.COM 
669710691STim.Szeto@Sun.COM 	/*
669810691STim.Szeto@Sun.COM 	 * set users return view entry index valid flag to false
669910691STim.Szeto@Sun.COM 	 * in case of failure
670010691STim.Szeto@Sun.COM 	 */
670110691STim.Szeto@Sun.COM 	viewEntry->veIndexValid = B_FALSE;
670210691STim.Szeto@Sun.COM 
670310691STim.Szeto@Sun.COM 	/* Check to ensure service exists */
670410691STim.Szeto@Sun.COM 	if (psCheckService() != STMF_STATUS_SUCCESS) {
670510691STim.Szeto@Sun.COM 		return (STMF_ERROR_SERVICE_NOT_FOUND);
670610691STim.Szeto@Sun.COM 	}
670710691STim.Szeto@Sun.COM 
670810691STim.Szeto@Sun.COM 	/* call init */
670910691STim.Szeto@Sun.COM 	ret = initializeConfig();
671010691STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
671110691STim.Szeto@Sun.COM 		return (ret);
671210691STim.Szeto@Sun.COM 	}
671310691STim.Szeto@Sun.COM 
671410691STim.Szeto@Sun.COM 	/*
671510691STim.Szeto@Sun.COM 	 * Open control node for stmf
671610691STim.Szeto@Sun.COM 	 */
671710691STim.Szeto@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
671810691STim.Szeto@Sun.COM 		return (ret);
671910691STim.Szeto@Sun.COM 
672010691STim.Szeto@Sun.COM 	/*
672110691STim.Szeto@Sun.COM 	 * Validate lun# in the view entry from the driver
672210691STim.Szeto@Sun.COM 	 */
672310691STim.Szeto@Sun.COM 	ret = validateLunNumIoctl(fd, &iViewEntry);
672410691STim.Szeto@Sun.COM 	(void) close(fd);
672510691STim.Szeto@Sun.COM 
672610691STim.Szeto@Sun.COM 	/* save available lun number */
672710691STim.Szeto@Sun.COM 	if (!viewEntry->luNbrValid) {
672810691STim.Szeto@Sun.COM 		bcopy(iViewEntry.luNbr, viewEntry->luNbr,
672910691STim.Szeto@Sun.COM 		    sizeof (iViewEntry.luNbr));
673010691STim.Szeto@Sun.COM 	}
673110691STim.Szeto@Sun.COM 
673210691STim.Szeto@Sun.COM 	return (ret);
673310691STim.Szeto@Sun.COM }
6734