xref: /onnv-gate/usr/src/lib/libstmf/common/stmf.c (revision 11116)
17836SJohn.Forte@Sun.COM /*
27836SJohn.Forte@Sun.COM  * CDDL HEADER START
37836SJohn.Forte@Sun.COM  *
47836SJohn.Forte@Sun.COM  * The contents of this file are subject to the terms of the
57836SJohn.Forte@Sun.COM  * Common Development and Distribution License (the "License").
67836SJohn.Forte@Sun.COM  * You may not use this file except in compliance with the License.
77836SJohn.Forte@Sun.COM  *
87836SJohn.Forte@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97836SJohn.Forte@Sun.COM  * or http://www.opensolaris.org/os/licensing.
107836SJohn.Forte@Sun.COM  * See the License for the specific language governing permissions
117836SJohn.Forte@Sun.COM  * and limitations under the License.
127836SJohn.Forte@Sun.COM  *
137836SJohn.Forte@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
147836SJohn.Forte@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157836SJohn.Forte@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
167836SJohn.Forte@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
177836SJohn.Forte@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
187836SJohn.Forte@Sun.COM  *
197836SJohn.Forte@Sun.COM  * CDDL HEADER END
207836SJohn.Forte@Sun.COM  */
217836SJohn.Forte@Sun.COM /*
229585STim.Szeto@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237836SJohn.Forte@Sun.COM  * Use is subject to license terms.
247836SJohn.Forte@Sun.COM  */
257836SJohn.Forte@Sun.COM 
267836SJohn.Forte@Sun.COM #include <stdlib.h>
277836SJohn.Forte@Sun.COM #include <stdio.h>
287836SJohn.Forte@Sun.COM #include <wchar.h>
297836SJohn.Forte@Sun.COM #include <strings.h>
307836SJohn.Forte@Sun.COM #include <sys/types.h>
317836SJohn.Forte@Sun.COM #include <sys/stat.h>
327836SJohn.Forte@Sun.COM #include <fcntl.h>
337836SJohn.Forte@Sun.COM #include <unistd.h>
347836SJohn.Forte@Sun.COM #include <libintl.h>
357836SJohn.Forte@Sun.COM #include <errno.h>
367836SJohn.Forte@Sun.COM #include <string.h>
377836SJohn.Forte@Sun.COM #include <assert.h>
387836SJohn.Forte@Sun.COM #include <libnvpair.h>
397836SJohn.Forte@Sun.COM #include <pthread.h>
407836SJohn.Forte@Sun.COM #include <syslog.h>
417836SJohn.Forte@Sun.COM #include <libstmf.h>
427836SJohn.Forte@Sun.COM #include <netinet/in.h>
437836SJohn.Forte@Sun.COM #include <inttypes.h>
447836SJohn.Forte@Sun.COM #include <store.h>
457836SJohn.Forte@Sun.COM #include <locale.h>
469585STim.Szeto@Sun.COM #include <math.h>
479585STim.Szeto@Sun.COM #include <libstmf_impl.h>
487836SJohn.Forte@Sun.COM #include <sys/stmf_ioctl.h>
499585STim.Szeto@Sun.COM #include <sys/stmf_sbd_ioctl.h>
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 
21449585STim.Szeto@Sun.COM 
21459585STim.Szeto@Sun.COM 	/* Check logical unit provider name to call correct dtype function */
21469585STim.Szeto@Sun.COM 	if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps))
21479585STim.Szeto@Sun.COM 	    != STMF_STATUS_SUCCESS) {
21489585STim.Szeto@Sun.COM 		return (ret);
21499585STim.Szeto@Sun.COM 	} else {
21509585STim.Szeto@Sun.COM 		if (strcmp(luProps.providerName, "sbd") == 0) {
21519585STim.Szeto@Sun.COM 			ret = getDiskAllProps(luGuid, hdl);
21529585STim.Szeto@Sun.COM 		} else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) {
21539585STim.Szeto@Sun.COM 			return (STMF_ERROR_NOT_FOUND);
21549585STim.Szeto@Sun.COM 		} else {
21559585STim.Szeto@Sun.COM 			return (STMF_ERROR_INVALID_ARG);
21569585STim.Szeto@Sun.COM 		}
21579585STim.Szeto@Sun.COM 	}
21589585STim.Szeto@Sun.COM 
21599585STim.Szeto@Sun.COM 	return (ret);
21609585STim.Szeto@Sun.COM }
21619585STim.Szeto@Sun.COM 
21629585STim.Szeto@Sun.COM /*
21639585STim.Szeto@Sun.COM  * getDiskAllProps
21649585STim.Szeto@Sun.COM  *
21659585STim.Szeto@Sun.COM  * Purpose: load all disk properties from sbd driver
21669585STim.Szeto@Sun.COM  *
21679585STim.Szeto@Sun.COM  * luGuid - guid of disk device for which properties are to be retrieved
21689585STim.Szeto@Sun.COM  * hdl - allocated luResource into which properties are to be copied
21699585STim.Szeto@Sun.COM  *
21709585STim.Szeto@Sun.COM  */
21719585STim.Szeto@Sun.COM static int
21729585STim.Szeto@Sun.COM getDiskAllProps(stmfGuid *luGuid, luResource *hdl)
21739585STim.Szeto@Sun.COM {
21749585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
21759585STim.Szeto@Sun.COM 	int fd;
21769585STim.Szeto@Sun.COM 	sbd_lu_props_t *sbdProps;
21779585STim.Szeto@Sun.COM 	int ioctlRet;
21789585STim.Szeto@Sun.COM 	int savedErrno;
21799585STim.Szeto@Sun.COM 	int sbdPropsSize = sizeof (*sbdProps) + MAX_SBD_PROPS;
21809585STim.Szeto@Sun.COM 	stmf_iocdata_t sbdIoctl = {0};
21819585STim.Szeto@Sun.COM 
21829585STim.Szeto@Sun.COM 	/*
21839585STim.Szeto@Sun.COM 	 * Open control node for sbd
21849585STim.Szeto@Sun.COM 	 */
21859585STim.Szeto@Sun.COM 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
21869585STim.Szeto@Sun.COM 		return (ret);
21879585STim.Szeto@Sun.COM 
21889585STim.Szeto@Sun.COM 
21899585STim.Szeto@Sun.COM 	*hdl = calloc(1, sizeof (luResourceImpl));
21909585STim.Szeto@Sun.COM 	if (*hdl == NULL) {
21919585STim.Szeto@Sun.COM 		(void) close(fd);
21929585STim.Szeto@Sun.COM 		return (STMF_ERROR_NOMEM);
21939585STim.Szeto@Sun.COM 	}
21949585STim.Szeto@Sun.COM 
21959585STim.Szeto@Sun.COM 	sbdProps = calloc(1, sbdPropsSize);
21969585STim.Szeto@Sun.COM 	if (sbdProps == NULL) {
21979585STim.Szeto@Sun.COM 		free(*hdl);
21989585STim.Szeto@Sun.COM 		(void) close(fd);
21999585STim.Szeto@Sun.COM 		return (STMF_ERROR_NOMEM);
22009585STim.Szeto@Sun.COM 	}
22019585STim.Szeto@Sun.COM 
22029585STim.Szeto@Sun.COM 	ret = createDiskResource((luResourceImpl *)*hdl);
22039585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
22049585STim.Szeto@Sun.COM 		free(*hdl);
220510725SJohn.Forte@Sun.COM 		free(sbdProps);
22069585STim.Szeto@Sun.COM 		(void) close(fd);
22079585STim.Szeto@Sun.COM 		return (ret);
22089585STim.Szeto@Sun.COM 	}
22099585STim.Szeto@Sun.COM 
22109585STim.Szeto@Sun.COM 	sbdProps->slp_input_guid = 1;
22119585STim.Szeto@Sun.COM 	bcopy(luGuid, sbdProps->slp_guid, sizeof (sbdProps->slp_guid));
22129585STim.Szeto@Sun.COM 
22139585STim.Szeto@Sun.COM 	sbdIoctl.stmf_version = STMF_VERSION_1;
22149585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf_size = sbdPropsSize;
22159585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdProps;
22169585STim.Szeto@Sun.COM 	sbdIoctl.stmf_obuf_size = sbdPropsSize;
22179585STim.Szeto@Sun.COM 	sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdProps;
22189585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, SBD_IOCTL_GET_LU_PROPS, &sbdIoctl);
22199585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
22209585STim.Szeto@Sun.COM 		savedErrno = errno;
22219585STim.Szeto@Sun.COM 		switch (savedErrno) {
22229585STim.Szeto@Sun.COM 			case EBUSY:
22239585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
22249585STim.Szeto@Sun.COM 				break;
22259585STim.Szeto@Sun.COM 			case EPERM:
22269585STim.Szeto@Sun.COM 			case EACCES:
22279585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
22289585STim.Szeto@Sun.COM 				break;
22299585STim.Szeto@Sun.COM 			case ENOENT:
22309585STim.Szeto@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
22319585STim.Szeto@Sun.COM 				break;
22329585STim.Szeto@Sun.COM 			default:
22339585STim.Szeto@Sun.COM 				syslog(LOG_DEBUG,
22349585STim.Szeto@Sun.COM 				    "getDiskAllProps:ioctl error(%d) (%d) (%d)",
22359585STim.Szeto@Sun.COM 				    ioctlRet, sbdIoctl.stmf_error, savedErrno);
22369585STim.Szeto@Sun.COM 				ret = STMF_STATUS_ERROR;
22379585STim.Szeto@Sun.COM 				break;
22389585STim.Szeto@Sun.COM 		}
22399585STim.Szeto@Sun.COM 	}
22409585STim.Szeto@Sun.COM 
22419585STim.Szeto@Sun.COM 	if (ret == STMF_STATUS_SUCCESS) {
22429585STim.Szeto@Sun.COM 		ret = loadDiskPropsFromDriver((luResourceImpl *)*hdl, sbdProps);
22439585STim.Szeto@Sun.COM 	}
22449585STim.Szeto@Sun.COM 
224510725SJohn.Forte@Sun.COM 	free(sbdProps);
22469585STim.Szeto@Sun.COM 	(void) close(fd);
22479585STim.Szeto@Sun.COM 	return (ret);
22489585STim.Szeto@Sun.COM }
22499585STim.Szeto@Sun.COM 
22509585STim.Szeto@Sun.COM /*
22519585STim.Szeto@Sun.COM  * loadDiskPropsFromDriver
22529585STim.Szeto@Sun.COM  *
22539585STim.Szeto@Sun.COM  * Purpose: Retrieve all disk type properties from sbd driver
22549585STim.Szeto@Sun.COM  *
22559585STim.Szeto@Sun.COM  * hdl - Allocated luResourceImpl
22569585STim.Szeto@Sun.COM  * sbdProps - sbd_lu_props_t structure returned from sbd driver
22579585STim.Szeto@Sun.COM  *
22589585STim.Szeto@Sun.COM  */
22599585STim.Szeto@Sun.COM static int
22609585STim.Szeto@Sun.COM loadDiskPropsFromDriver(luResourceImpl *hdl, sbd_lu_props_t *sbdProps)
22619585STim.Szeto@Sun.COM {
22629585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
22639585STim.Szeto@Sun.COM 	diskResource *diskLu = hdl->resource;
22649585STim.Szeto@Sun.COM 	/* copy guid */
22659585STim.Szeto@Sun.COM 	diskLu->luGuidValid = B_TRUE;
22669585STim.Szeto@Sun.COM 	bcopy(sbdProps->slp_guid, diskLu->luGuid, sizeof (sbdProps->slp_guid));
22679585STim.Szeto@Sun.COM 
22689585STim.Szeto@Sun.COM 	if (sbdProps->slp_separate_meta && sbdProps->slp_meta_fname_valid) {
22699585STim.Szeto@Sun.COM 		diskLu->luMetaFileNameValid = B_TRUE;
22709585STim.Szeto@Sun.COM 		if (strlcpy(diskLu->luMetaFileName,
22719585STim.Szeto@Sun.COM 		    (char *)&(sbdProps->slp_buf[sbdProps->slp_meta_fname_off]),
22729585STim.Szeto@Sun.COM 		    sizeof (diskLu->luMetaFileName)) >=
22739585STim.Szeto@Sun.COM 		    sizeof (diskLu->luMetaFileName)) {
22749585STim.Szeto@Sun.COM 			return (STMF_STATUS_ERROR);
22759585STim.Szeto@Sun.COM 		}
22769585STim.Szeto@Sun.COM 	}
22779585STim.Szeto@Sun.COM 
22789585STim.Szeto@Sun.COM 	if (sbdProps->slp_data_fname_valid) {
22799585STim.Szeto@Sun.COM 		diskLu->luDataFileNameValid = B_TRUE;
22809585STim.Szeto@Sun.COM 		if (strlcpy(diskLu->luDataFileName,
22819585STim.Szeto@Sun.COM 		    (char *)&(sbdProps->slp_buf[sbdProps->slp_data_fname_off]),
22829585STim.Szeto@Sun.COM 		    sizeof (diskLu->luDataFileName)) >=
22839585STim.Szeto@Sun.COM 		    sizeof (diskLu->luDataFileName)) {
22849585STim.Szeto@Sun.COM 			return (STMF_STATUS_ERROR);
22859585STim.Szeto@Sun.COM 		}
22869585STim.Szeto@Sun.COM 	}
22879585STim.Szeto@Sun.COM 
22889585STim.Szeto@Sun.COM 	if (sbdProps->slp_serial_valid) {
22899585STim.Szeto@Sun.COM 		diskLu->serialNumValid = B_TRUE;
22909585STim.Szeto@Sun.COM 		bcopy(&(sbdProps->slp_buf[sbdProps->slp_serial_off]),
22919585STim.Szeto@Sun.COM 		    diskLu->serialNum, sbdProps->slp_serial_size);
22929585STim.Szeto@Sun.COM 	}
22939585STim.Szeto@Sun.COM 
229410113SNattuvetty.Bhavyan@Sun.COM 	if (sbdProps->slp_mgmt_url_valid) {
229510113SNattuvetty.Bhavyan@Sun.COM 		diskLu->luMgmtUrlValid = B_TRUE;
229610113SNattuvetty.Bhavyan@Sun.COM 		if (strlcpy(diskLu->luMgmtUrl,
229710113SNattuvetty.Bhavyan@Sun.COM 		    (char *)&(sbdProps->slp_buf[sbdProps->slp_mgmt_url_off]),
229810113SNattuvetty.Bhavyan@Sun.COM 		    sizeof (diskLu->luMgmtUrl)) >=
229910113SNattuvetty.Bhavyan@Sun.COM 		    sizeof (diskLu->luMgmtUrl)) {
230010113SNattuvetty.Bhavyan@Sun.COM 			return (STMF_STATUS_ERROR);
230110113SNattuvetty.Bhavyan@Sun.COM 		}
230210113SNattuvetty.Bhavyan@Sun.COM 	}
230310113SNattuvetty.Bhavyan@Sun.COM 
23049585STim.Szeto@Sun.COM 	if (sbdProps->slp_alias_valid) {
23059585STim.Szeto@Sun.COM 		diskLu->luAliasValid = B_TRUE;
23069585STim.Szeto@Sun.COM 		if (strlcpy(diskLu->luAlias,
23079585STim.Szeto@Sun.COM 		    (char *)&(sbdProps->slp_buf[sbdProps->slp_alias_off]),
23089585STim.Szeto@Sun.COM 		    sizeof (diskLu->luAlias)) >=
23099585STim.Szeto@Sun.COM 		    sizeof (diskLu->luAlias)) {
23109585STim.Szeto@Sun.COM 			return (STMF_STATUS_ERROR);
23119585STim.Szeto@Sun.COM 		}
23129585STim.Szeto@Sun.COM 	} else { /* set alias to data filename if not set */
23139585STim.Szeto@Sun.COM 		if (sbdProps->slp_data_fname_valid) {
23149585STim.Szeto@Sun.COM 			diskLu->luAliasValid = B_TRUE;
23159585STim.Szeto@Sun.COM 			if (strlcpy(diskLu->luAlias,
23169585STim.Szeto@Sun.COM 			    (char *)&(sbdProps->slp_buf[
23179585STim.Szeto@Sun.COM 			    sbdProps->slp_data_fname_off]),
23189585STim.Szeto@Sun.COM 			    sizeof (diskLu->luAlias)) >=
23199585STim.Szeto@Sun.COM 			    sizeof (diskLu->luAlias)) {
23209585STim.Szeto@Sun.COM 				return (STMF_STATUS_ERROR);
23219585STim.Szeto@Sun.COM 			}
23229585STim.Szeto@Sun.COM 		}
23239585STim.Szeto@Sun.COM 	}
23249585STim.Szeto@Sun.COM 
23259585STim.Szeto@Sun.COM 	diskLu->vidValid = B_TRUE;
23269585STim.Szeto@Sun.COM 	bcopy(sbdProps->slp_vid, diskLu->vid, sizeof (diskLu->vid));
23279585STim.Szeto@Sun.COM 
23289585STim.Szeto@Sun.COM 	diskLu->pidValid = B_TRUE;
23299585STim.Szeto@Sun.COM 	bcopy(sbdProps->slp_pid, diskLu->pid, sizeof (diskLu->pid));
23309585STim.Szeto@Sun.COM 
23319585STim.Szeto@Sun.COM 	diskLu->revValid = B_TRUE;
23329585STim.Szeto@Sun.COM 	bcopy(sbdProps->slp_rev, diskLu->rev, sizeof (diskLu->rev));
23339585STim.Szeto@Sun.COM 
23349585STim.Szeto@Sun.COM 	diskLu->writeProtectEnableValid = B_TRUE;
23359585STim.Szeto@Sun.COM 	if (sbdProps->slp_write_protected) {
23369585STim.Szeto@Sun.COM 		diskLu->writeProtectEnable = B_TRUE;
23379585STim.Szeto@Sun.COM 	}
23389585STim.Szeto@Sun.COM 
23399585STim.Szeto@Sun.COM 	diskLu->writebackCacheDisableValid = B_TRUE;
23409585STim.Szeto@Sun.COM 	if (sbdProps->slp_writeback_cache_disable_cur) {
23419585STim.Szeto@Sun.COM 		diskLu->writebackCacheDisable = B_TRUE;
23429585STim.Szeto@Sun.COM 	}
23439585STim.Szeto@Sun.COM 
23449585STim.Szeto@Sun.COM 	diskLu->blkSizeValid = B_TRUE;
23459585STim.Szeto@Sun.COM 	diskLu->blkSize = sbdProps->slp_blksize;
23469585STim.Szeto@Sun.COM 
23479585STim.Szeto@Sun.COM 	diskLu->luSizeValid = B_TRUE;
23489585STim.Szeto@Sun.COM 	diskLu->luSize = sbdProps->slp_lu_size;
23499585STim.Szeto@Sun.COM 
235010725SJohn.Forte@Sun.COM 	diskLu->accessState = sbdProps->slp_access_state;
235110725SJohn.Forte@Sun.COM 
23529585STim.Szeto@Sun.COM 	return (ret);
23539585STim.Szeto@Sun.COM }
23549585STim.Szeto@Sun.COM 
235511103SJohn.Forte@Sun.COM /*
235611103SJohn.Forte@Sun.COM  * stmfGetGlobalLuProp
235711103SJohn.Forte@Sun.COM  *
235811103SJohn.Forte@Sun.COM  * Purpose: get a global property for a device type
235911103SJohn.Forte@Sun.COM  *
236011103SJohn.Forte@Sun.COM  */
236111103SJohn.Forte@Sun.COM int
236211103SJohn.Forte@Sun.COM stmfGetGlobalLuProp(uint16_t dType, uint32_t prop, char *propVal,
236311103SJohn.Forte@Sun.COM     size_t *propLen)
236411103SJohn.Forte@Sun.COM {
236511103SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
236611103SJohn.Forte@Sun.COM 	if (dType != STMF_DISK || propVal == NULL) {
236711103SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
236811103SJohn.Forte@Sun.COM 	}
236911103SJohn.Forte@Sun.COM 
237011103SJohn.Forte@Sun.COM 	ret = getDiskGlobalProp(prop, propVal, propLen);
237111103SJohn.Forte@Sun.COM 
237211103SJohn.Forte@Sun.COM 	return (ret);
237311103SJohn.Forte@Sun.COM }
237411103SJohn.Forte@Sun.COM 
237511103SJohn.Forte@Sun.COM /*
237611103SJohn.Forte@Sun.COM  * getDiskGlobalProp
237711103SJohn.Forte@Sun.COM  *
237811103SJohn.Forte@Sun.COM  * Purpose: get global property from sbd driver
237911103SJohn.Forte@Sun.COM  *
238011103SJohn.Forte@Sun.COM  */
238111103SJohn.Forte@Sun.COM static int
238211103SJohn.Forte@Sun.COM getDiskGlobalProp(uint32_t prop, char *propVal, size_t *propLen)
238311103SJohn.Forte@Sun.COM {
238411103SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
238511103SJohn.Forte@Sun.COM 	int fd;
238611103SJohn.Forte@Sun.COM 	sbd_global_props_t *sbdProps;
238711103SJohn.Forte@Sun.COM 	void *sbd_realloc;
238811103SJohn.Forte@Sun.COM 	int retryCnt = 0;
238911103SJohn.Forte@Sun.COM 	boolean_t retry;
239011103SJohn.Forte@Sun.COM 	int ioctlRet;
239111103SJohn.Forte@Sun.COM 	int savedErrno;
239211103SJohn.Forte@Sun.COM 	int sbdPropsSize = sizeof (*sbdProps) + MAX_SBD_PROPS;
239311103SJohn.Forte@Sun.COM 	stmf_iocdata_t sbdIoctl = {0};
239411103SJohn.Forte@Sun.COM 	size_t reqLen;
239511103SJohn.Forte@Sun.COM 
239611103SJohn.Forte@Sun.COM 	switch (prop) {
239711103SJohn.Forte@Sun.COM 		case STMF_LU_PROP_MGMT_URL:
239811103SJohn.Forte@Sun.COM 			break;
239911103SJohn.Forte@Sun.COM 		default:
240011103SJohn.Forte@Sun.COM 			return (STMF_ERROR_INVALID_PROP);
240111103SJohn.Forte@Sun.COM 	}
240211103SJohn.Forte@Sun.COM 
240311103SJohn.Forte@Sun.COM 	/*
240411103SJohn.Forte@Sun.COM 	 * Open control node for sbd
240511103SJohn.Forte@Sun.COM 	 */
240611103SJohn.Forte@Sun.COM 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
240711103SJohn.Forte@Sun.COM 		return (ret);
240811103SJohn.Forte@Sun.COM 
240911103SJohn.Forte@Sun.COM 	sbdProps = calloc(1, sbdPropsSize);
241011103SJohn.Forte@Sun.COM 	if (sbdProps == NULL) {
241111103SJohn.Forte@Sun.COM 		(void) close(fd);
241211103SJohn.Forte@Sun.COM 		return (STMF_ERROR_NOMEM);
241311103SJohn.Forte@Sun.COM 	}
241411103SJohn.Forte@Sun.COM 
241511103SJohn.Forte@Sun.COM 	do {
241611103SJohn.Forte@Sun.COM 		retry = B_FALSE;
241711103SJohn.Forte@Sun.COM 		sbdIoctl.stmf_version = STMF_VERSION_1;
241811103SJohn.Forte@Sun.COM 		sbdIoctl.stmf_obuf_size = sbdPropsSize;
241911103SJohn.Forte@Sun.COM 		sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdProps;
242011103SJohn.Forte@Sun.COM 		ioctlRet = ioctl(fd, SBD_IOCTL_GET_GLOBAL_LU, &sbdIoctl);
242111103SJohn.Forte@Sun.COM 		if (ioctlRet != 0) {
242211103SJohn.Forte@Sun.COM 			savedErrno = errno;
242311103SJohn.Forte@Sun.COM 			switch (savedErrno) {
242411103SJohn.Forte@Sun.COM 				case EBUSY:
242511103SJohn.Forte@Sun.COM 					ret = STMF_ERROR_BUSY;
242611103SJohn.Forte@Sun.COM 					break;
242711103SJohn.Forte@Sun.COM 				case EPERM:
242811103SJohn.Forte@Sun.COM 				case EACCES:
242911103SJohn.Forte@Sun.COM 					ret = STMF_ERROR_PERM;
243011103SJohn.Forte@Sun.COM 					break;
243111103SJohn.Forte@Sun.COM 				case ENOMEM:
243211103SJohn.Forte@Sun.COM 					if (sbdIoctl.stmf_error ==
243311103SJohn.Forte@Sun.COM 					    SBD_RET_INSUFFICIENT_BUF_SPACE &&
243411103SJohn.Forte@Sun.COM 					    retryCnt++ < 3) {
243511103SJohn.Forte@Sun.COM 						sbdPropsSize =
243611103SJohn.Forte@Sun.COM 						    sizeof (*sbdProps) +
243711103SJohn.Forte@Sun.COM 						    sbdProps->
243811103SJohn.Forte@Sun.COM 						    mlu_buf_size_needed;
243911103SJohn.Forte@Sun.COM 
244011103SJohn.Forte@Sun.COM 						sbd_realloc = sbdProps;
244111103SJohn.Forte@Sun.COM 						sbdProps = realloc(sbdProps,
244211103SJohn.Forte@Sun.COM 						    sbdPropsSize);
244311103SJohn.Forte@Sun.COM 						if (sbdProps == NULL) {
244411103SJohn.Forte@Sun.COM 							free(sbd_realloc);
244511103SJohn.Forte@Sun.COM 							ret = STMF_ERROR_NOMEM;
244611103SJohn.Forte@Sun.COM 							break;
244711103SJohn.Forte@Sun.COM 						}
244811103SJohn.Forte@Sun.COM 						retry = B_TRUE;
244911103SJohn.Forte@Sun.COM 					} else {
245011103SJohn.Forte@Sun.COM 						ret = STMF_ERROR_NOMEM;
245111103SJohn.Forte@Sun.COM 					}
245211103SJohn.Forte@Sun.COM 					break;
245311103SJohn.Forte@Sun.COM 				default:
245411103SJohn.Forte@Sun.COM 					syslog(LOG_DEBUG,
245511103SJohn.Forte@Sun.COM 					    "getDiskGlobalProp:ioctl error(%d)"
245611103SJohn.Forte@Sun.COM 					    "(%d)(%d)", ioctlRet,
245711103SJohn.Forte@Sun.COM 					    sbdIoctl.stmf_error, savedErrno);
245811103SJohn.Forte@Sun.COM 					ret = STMF_STATUS_ERROR;
245911103SJohn.Forte@Sun.COM 					break;
246011103SJohn.Forte@Sun.COM 			}
246111103SJohn.Forte@Sun.COM 
246211103SJohn.Forte@Sun.COM 		}
246311103SJohn.Forte@Sun.COM 	} while (retry);
246411103SJohn.Forte@Sun.COM 
246511103SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
246611103SJohn.Forte@Sun.COM 		goto done;
246711103SJohn.Forte@Sun.COM 	}
246811103SJohn.Forte@Sun.COM 
246911103SJohn.Forte@Sun.COM 	switch (prop) {
247011103SJohn.Forte@Sun.COM 		case STMF_LU_PROP_MGMT_URL:
247111103SJohn.Forte@Sun.COM 			if (sbdProps->mlu_mgmt_url_valid == 0) {
247211103SJohn.Forte@Sun.COM 				ret = STMF_ERROR_NO_PROP;
247311103SJohn.Forte@Sun.COM 				goto done;
247411103SJohn.Forte@Sun.COM 			}
247511103SJohn.Forte@Sun.COM 			if ((reqLen = strlcpy(propVal, (char *)&(
247611103SJohn.Forte@Sun.COM 			    sbdProps->mlu_buf[sbdProps->mlu_mgmt_url_off]),
247711103SJohn.Forte@Sun.COM 			    *propLen)) >= *propLen) {
247811103SJohn.Forte@Sun.COM 				*propLen = reqLen + 1;
247911103SJohn.Forte@Sun.COM 				ret = STMF_ERROR_INVALID_ARG;
248011103SJohn.Forte@Sun.COM 				goto done;
248111103SJohn.Forte@Sun.COM 			}
248211103SJohn.Forte@Sun.COM 			break;
248311103SJohn.Forte@Sun.COM 	}
248411103SJohn.Forte@Sun.COM 
248511103SJohn.Forte@Sun.COM done:
248611103SJohn.Forte@Sun.COM 	free(sbdProps);
248711103SJohn.Forte@Sun.COM 	(void) close(fd);
248811103SJohn.Forte@Sun.COM 	return (ret);
248911103SJohn.Forte@Sun.COM }
249011103SJohn.Forte@Sun.COM 
249111103SJohn.Forte@Sun.COM /*
249211103SJohn.Forte@Sun.COM  * stmfSetGlobalLuProp
249311103SJohn.Forte@Sun.COM  *
249411103SJohn.Forte@Sun.COM  * Purpose: set a global property for a device type
249511103SJohn.Forte@Sun.COM  *
249611103SJohn.Forte@Sun.COM  */
249711103SJohn.Forte@Sun.COM int
249811103SJohn.Forte@Sun.COM stmfSetGlobalLuProp(uint16_t dType, uint32_t prop, const char *propVal)
249911103SJohn.Forte@Sun.COM {
250011103SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
250111103SJohn.Forte@Sun.COM 	if (dType != STMF_DISK || propVal == NULL) {
250211103SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
250311103SJohn.Forte@Sun.COM 	}
250411103SJohn.Forte@Sun.COM 
250511103SJohn.Forte@Sun.COM 	ret = setDiskGlobalProp(prop, propVal);
250611103SJohn.Forte@Sun.COM 
250711103SJohn.Forte@Sun.COM 	return (ret);
250811103SJohn.Forte@Sun.COM }
250911103SJohn.Forte@Sun.COM 
251011103SJohn.Forte@Sun.COM /*
251111103SJohn.Forte@Sun.COM  * setDiskGlobalProp
251211103SJohn.Forte@Sun.COM  *
251311103SJohn.Forte@Sun.COM  * Purpose: set properties for resource of type disk
251411103SJohn.Forte@Sun.COM  *
251511103SJohn.Forte@Sun.COM  * resourceProp - valid resource identifier
251611103SJohn.Forte@Sun.COM  * propVal - valid resource value
251711103SJohn.Forte@Sun.COM  */
251811103SJohn.Forte@Sun.COM static int
251911103SJohn.Forte@Sun.COM setDiskGlobalProp(uint32_t resourceProp, const char *propVal)
252011103SJohn.Forte@Sun.COM {
252111103SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
252211103SJohn.Forte@Sun.COM 	sbd_global_props_t *sbdGlobalProps = NULL;
252311103SJohn.Forte@Sun.COM 	int sbdGlobalPropsSize = 0;
252411103SJohn.Forte@Sun.COM 	int propLen;
252511103SJohn.Forte@Sun.COM 	int mluBufSize = 0;
252611103SJohn.Forte@Sun.COM 	int fd;
252711103SJohn.Forte@Sun.COM 	int savedErrno;
252811103SJohn.Forte@Sun.COM 	int ioctlRet;
252911103SJohn.Forte@Sun.COM 	stmf_iocdata_t sbdIoctl = {0};
253011103SJohn.Forte@Sun.COM 
253111103SJohn.Forte@Sun.COM 	switch (resourceProp) {
253211103SJohn.Forte@Sun.COM 		case STMF_LU_PROP_MGMT_URL:
253311103SJohn.Forte@Sun.COM 			break;
253411103SJohn.Forte@Sun.COM 		default:
253511103SJohn.Forte@Sun.COM 			return (STMF_ERROR_INVALID_PROP);
253611103SJohn.Forte@Sun.COM 			break;
253711103SJohn.Forte@Sun.COM 	}
253811103SJohn.Forte@Sun.COM 
253911103SJohn.Forte@Sun.COM 	/*
254011103SJohn.Forte@Sun.COM 	 * Open control node for sbd
254111103SJohn.Forte@Sun.COM 	 */
254211103SJohn.Forte@Sun.COM 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
254311103SJohn.Forte@Sun.COM 		return (ret);
254411103SJohn.Forte@Sun.COM 
254511103SJohn.Forte@Sun.COM 	propLen = strlen(propVal);
254611103SJohn.Forte@Sun.COM 	mluBufSize += propLen + 1;
254711103SJohn.Forte@Sun.COM 	sbdGlobalPropsSize += sizeof (sbd_global_props_t) - 8 +
254811103SJohn.Forte@Sun.COM 	    max(8, mluBufSize);
254911103SJohn.Forte@Sun.COM 	/*
255011103SJohn.Forte@Sun.COM 	 * 8 is the size of the buffer set aside for
255111103SJohn.Forte@Sun.COM 	 * concatenation of variable length fields
255211103SJohn.Forte@Sun.COM 	 */
255311103SJohn.Forte@Sun.COM 	sbdGlobalProps = (sbd_global_props_t *)calloc(1, sbdGlobalPropsSize);
255411103SJohn.Forte@Sun.COM 	if (sbdGlobalProps == NULL) {
255511103SJohn.Forte@Sun.COM 		(void) close(fd);
255611103SJohn.Forte@Sun.COM 		return (STMF_ERROR_NOMEM);
255711103SJohn.Forte@Sun.COM 	}
255811103SJohn.Forte@Sun.COM 
255911103SJohn.Forte@Sun.COM 	sbdGlobalProps->mlu_struct_size = sbdGlobalPropsSize;
256011103SJohn.Forte@Sun.COM 
256111103SJohn.Forte@Sun.COM 	switch (resourceProp) {
256211103SJohn.Forte@Sun.COM 		case STMF_LU_PROP_MGMT_URL:
256311103SJohn.Forte@Sun.COM 			sbdGlobalProps->mlu_mgmt_url_valid = 1;
256411103SJohn.Forte@Sun.COM 			bcopy(propVal, &(sbdGlobalProps->mlu_buf),
256511103SJohn.Forte@Sun.COM 			    propLen + 1);
256611103SJohn.Forte@Sun.COM 			break;
256711103SJohn.Forte@Sun.COM 		default:
256811103SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NO_PROP;
256911103SJohn.Forte@Sun.COM 			goto done;
257011103SJohn.Forte@Sun.COM 	}
257111103SJohn.Forte@Sun.COM 
257211103SJohn.Forte@Sun.COM 	sbdIoctl.stmf_version = STMF_VERSION_1;
257311103SJohn.Forte@Sun.COM 	sbdIoctl.stmf_ibuf_size = sbdGlobalProps->mlu_struct_size;
257411103SJohn.Forte@Sun.COM 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdGlobalProps;
257511103SJohn.Forte@Sun.COM 
257611103SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, SBD_IOCTL_SET_GLOBAL_LU, &sbdIoctl);
257711103SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
257811103SJohn.Forte@Sun.COM 		savedErrno = errno;
257911103SJohn.Forte@Sun.COM 		switch (savedErrno) {
258011103SJohn.Forte@Sun.COM 			case EBUSY:
258111103SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
258211103SJohn.Forte@Sun.COM 				break;
258311103SJohn.Forte@Sun.COM 			case EPERM:
258411103SJohn.Forte@Sun.COM 			case EACCES:
258511103SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
258611103SJohn.Forte@Sun.COM 				break;
258711103SJohn.Forte@Sun.COM 			default:
258811103SJohn.Forte@Sun.COM 				diskError(sbdIoctl.stmf_error, &ret);
258911103SJohn.Forte@Sun.COM 				if (ret == STMF_STATUS_ERROR) {
259011103SJohn.Forte@Sun.COM 					syslog(LOG_DEBUG,
259111103SJohn.Forte@Sun.COM 					"modifyDiskLu:ioctl "
259211103SJohn.Forte@Sun.COM 					"error(%d) (%d) (%d)", ioctlRet,
259311103SJohn.Forte@Sun.COM 					    sbdIoctl.stmf_error, savedErrno);
259411103SJohn.Forte@Sun.COM 				}
259511103SJohn.Forte@Sun.COM 				break;
259611103SJohn.Forte@Sun.COM 		}
259711103SJohn.Forte@Sun.COM 	}
259811103SJohn.Forte@Sun.COM 
259911103SJohn.Forte@Sun.COM done:
260011103SJohn.Forte@Sun.COM 	free(sbdGlobalProps);
260111103SJohn.Forte@Sun.COM 	(void) close(fd);
260211103SJohn.Forte@Sun.COM 	return (ret);
260311103SJohn.Forte@Sun.COM }
260411103SJohn.Forte@Sun.COM 
26059585STim.Szeto@Sun.COM 
26069585STim.Szeto@Sun.COM /*
26079585STim.Szeto@Sun.COM  * stmfSetLuProp
26089585STim.Szeto@Sun.COM  *
26099585STim.Szeto@Sun.COM  * Purpose: set a property on an luResource
26109585STim.Szeto@Sun.COM  *
26119585STim.Szeto@Sun.COM  * hdl - allocated luResource
26129585STim.Szeto@Sun.COM  * prop - property identifier
26139585STim.Szeto@Sun.COM  * propVal - property value to be set
26149585STim.Szeto@Sun.COM  */
26159585STim.Szeto@Sun.COM int
26169585STim.Szeto@Sun.COM stmfSetLuProp(luResource hdl, uint32_t prop, const char *propVal)
26179585STim.Szeto@Sun.COM {
26189585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
26199585STim.Szeto@Sun.COM 	luResourceImpl *luPropsHdl = hdl;
26209585STim.Szeto@Sun.COM 	if (hdl == NULL) {
26219585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
26229585STim.Szeto@Sun.COM 	}
26239585STim.Szeto@Sun.COM 
26249585STim.Szeto@Sun.COM 	if (luPropsHdl->type == STMF_DISK) {
26259585STim.Szeto@Sun.COM 		ret = setDiskProp(luPropsHdl, prop, propVal);
26269585STim.Szeto@Sun.COM 	} else {
26279585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
26289585STim.Szeto@Sun.COM 	}
26299585STim.Szeto@Sun.COM 
26309585STim.Szeto@Sun.COM 	return (ret);
26319585STim.Szeto@Sun.COM }
26329585STim.Szeto@Sun.COM 
26339585STim.Szeto@Sun.COM /*
26349585STim.Szeto@Sun.COM  * getDiskProp
26359585STim.Szeto@Sun.COM  *
26369585STim.Szeto@Sun.COM  * Purpose: retrieve a given property from a logical unit resource of type disk
26379585STim.Szeto@Sun.COM  *
26389585STim.Szeto@Sun.COM  * hdl - allocated luResourceImpl
26399585STim.Szeto@Sun.COM  * prop - property identifier
26409585STim.Szeto@Sun.COM  * propVal - pointer to character to contain the retrieved property value
26419585STim.Szeto@Sun.COM  * propLen - On input this is the length of propVal. On failure, it contains the
26429585STim.Szeto@Sun.COM  *           number of bytes required for propVal
26439585STim.Szeto@Sun.COM  */
26449585STim.Szeto@Sun.COM static int
26459585STim.Szeto@Sun.COM getDiskProp(luResourceImpl *hdl, uint32_t prop, char *propVal, size_t *propLen)
26469585STim.Szeto@Sun.COM {
26479585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
26489585STim.Szeto@Sun.COM 	diskResource *diskLu = hdl->resource;
264910725SJohn.Forte@Sun.COM 	char accessState[20];
26509585STim.Szeto@Sun.COM 	size_t reqLen;
26519585STim.Szeto@Sun.COM 
265210725SJohn.Forte@Sun.COM 	if (prop == STMF_LU_PROP_ACCESS_STATE) {
265310725SJohn.Forte@Sun.COM 		if (diskLu->accessState == SBD_LU_ACTIVE) {
265410725SJohn.Forte@Sun.COM 			(void) strlcpy(accessState, STMF_ACCESS_ACTIVE,
265510725SJohn.Forte@Sun.COM 			    sizeof (accessState));
265610725SJohn.Forte@Sun.COM 		} else if (diskLu->accessState == SBD_LU_TRANSITION_TO_ACTIVE) {
265710725SJohn.Forte@Sun.COM 			(void) strlcpy(accessState,
265810725SJohn.Forte@Sun.COM 			    STMF_ACCESS_STANDBY_TO_ACTIVE,
265910725SJohn.Forte@Sun.COM 			    sizeof (accessState));
266010725SJohn.Forte@Sun.COM 		} else if (diskLu->accessState == SBD_LU_STANDBY) {
266110725SJohn.Forte@Sun.COM 			(void) strlcpy(accessState, STMF_ACCESS_STANDBY,
266210725SJohn.Forte@Sun.COM 			    sizeof (accessState));
266310725SJohn.Forte@Sun.COM 		} else if (diskLu->accessState ==
266410725SJohn.Forte@Sun.COM 		    SBD_LU_TRANSITION_TO_STANDBY) {
266510725SJohn.Forte@Sun.COM 			(void) strlcpy(accessState,
266610725SJohn.Forte@Sun.COM 			    STMF_ACCESS_ACTIVE_TO_STANDBY,
266710725SJohn.Forte@Sun.COM 			    sizeof (accessState));
266810725SJohn.Forte@Sun.COM 		}
266910725SJohn.Forte@Sun.COM 		if ((reqLen = strlcpy(propVal, accessState,
267010725SJohn.Forte@Sun.COM 		    *propLen)) >= *propLen) {
267110725SJohn.Forte@Sun.COM 			*propLen = reqLen + 1;
267210725SJohn.Forte@Sun.COM 			return (STMF_ERROR_INVALID_ARG);
267310725SJohn.Forte@Sun.COM 		}
267410725SJohn.Forte@Sun.COM 		return (0);
267510725SJohn.Forte@Sun.COM 	}
267610725SJohn.Forte@Sun.COM 
267710725SJohn.Forte@Sun.COM 	if (diskLu->accessState != SBD_LU_ACTIVE) {
267810725SJohn.Forte@Sun.COM 		return (STMF_ERROR_NO_PROP_STANDBY);
267910725SJohn.Forte@Sun.COM 	}
268010725SJohn.Forte@Sun.COM 
26819585STim.Szeto@Sun.COM 	switch (prop) {
26829585STim.Szeto@Sun.COM 		case STMF_LU_PROP_BLOCK_SIZE:
26839585STim.Szeto@Sun.COM 			if (diskLu->blkSizeValid == B_FALSE) {
26849585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
26859585STim.Szeto@Sun.COM 			}
26869585STim.Szeto@Sun.COM 			reqLen = snprintf(propVal, *propLen, "%llu",
26879585STim.Szeto@Sun.COM 			    (u_longlong_t)diskLu->blkSize);
26889585STim.Szeto@Sun.COM 			if (reqLen >= *propLen) {
26899585STim.Szeto@Sun.COM 				*propLen = reqLen + 1;
26909585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
26919585STim.Szeto@Sun.COM 			}
26929585STim.Szeto@Sun.COM 			break;
26939585STim.Szeto@Sun.COM 		case STMF_LU_PROP_FILENAME:
26949585STim.Szeto@Sun.COM 			if (diskLu->luDataFileNameValid == B_FALSE) {
26959585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
26969585STim.Szeto@Sun.COM 			}
26979585STim.Szeto@Sun.COM 			if ((reqLen = strlcpy(propVal, diskLu->luDataFileName,
26989585STim.Szeto@Sun.COM 			    *propLen)) >= *propLen) {
26999585STim.Szeto@Sun.COM 				*propLen = reqLen + 1;
27009585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
27019585STim.Szeto@Sun.COM 			}
27029585STim.Szeto@Sun.COM 			break;
27039585STim.Szeto@Sun.COM 		case STMF_LU_PROP_META_FILENAME:
27049585STim.Szeto@Sun.COM 			if (diskLu->luMetaFileNameValid == B_FALSE) {
27059585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
27069585STim.Szeto@Sun.COM 			}
27079585STim.Szeto@Sun.COM 			if ((reqLen = strlcpy(propVal, diskLu->luMetaFileName,
27089585STim.Szeto@Sun.COM 			    *propLen)) >= *propLen) {
27099585STim.Szeto@Sun.COM 				*propLen = reqLen + 1;
27109585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
27119585STim.Szeto@Sun.COM 			}
27129585STim.Szeto@Sun.COM 			break;
271310113SNattuvetty.Bhavyan@Sun.COM 		case STMF_LU_PROP_MGMT_URL:
271410113SNattuvetty.Bhavyan@Sun.COM 			if (diskLu->luMgmtUrlValid == B_FALSE) {
271510113SNattuvetty.Bhavyan@Sun.COM 				return (STMF_ERROR_NO_PROP);
271610113SNattuvetty.Bhavyan@Sun.COM 			}
271710113SNattuvetty.Bhavyan@Sun.COM 			if ((reqLen = strlcpy(propVal, diskLu->luMgmtUrl,
271810113SNattuvetty.Bhavyan@Sun.COM 			    *propLen)) >= *propLen) {
271910113SNattuvetty.Bhavyan@Sun.COM 				*propLen = reqLen + 1;
272010113SNattuvetty.Bhavyan@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
272110113SNattuvetty.Bhavyan@Sun.COM 			}
272210113SNattuvetty.Bhavyan@Sun.COM 			break;
27239585STim.Szeto@Sun.COM 		case STMF_LU_PROP_GUID:
27249585STim.Szeto@Sun.COM 			if (diskLu->luGuidValid == B_FALSE) {
27259585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
27269585STim.Szeto@Sun.COM 			}
27279585STim.Szeto@Sun.COM 			reqLen = snprintf(propVal, *propLen,
27289585STim.Szeto@Sun.COM 			    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X"
27299585STim.Szeto@Sun.COM 			    "%02X%02X%02X%02X",
27309585STim.Szeto@Sun.COM 			    diskLu->luGuid[0], diskLu->luGuid[1],
27319585STim.Szeto@Sun.COM 			    diskLu->luGuid[2], diskLu->luGuid[3],
27329585STim.Szeto@Sun.COM 			    diskLu->luGuid[4], diskLu->luGuid[5],
27339585STim.Szeto@Sun.COM 			    diskLu->luGuid[6], diskLu->luGuid[7],
27349585STim.Szeto@Sun.COM 			    diskLu->luGuid[8], diskLu->luGuid[9],
27359585STim.Szeto@Sun.COM 			    diskLu->luGuid[10], diskLu->luGuid[11],
27369585STim.Szeto@Sun.COM 			    diskLu->luGuid[12], diskLu->luGuid[13],
27379585STim.Szeto@Sun.COM 			    diskLu->luGuid[14], diskLu->luGuid[15]);
27389585STim.Szeto@Sun.COM 			if (reqLen >= *propLen) {
27399585STim.Szeto@Sun.COM 				*propLen = reqLen + 1;
27409585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
27419585STim.Szeto@Sun.COM 			}
27429585STim.Szeto@Sun.COM 			break;
27439585STim.Szeto@Sun.COM 		case STMF_LU_PROP_SERIAL_NUM:
27449585STim.Szeto@Sun.COM 			if (diskLu->serialNumValid == B_FALSE) {
27459585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
27469585STim.Szeto@Sun.COM 			}
27479585STim.Szeto@Sun.COM 			if ((reqLen = strlcpy(propVal, diskLu->serialNum,
27489585STim.Szeto@Sun.COM 			    *propLen)) >= *propLen) {
27499585STim.Szeto@Sun.COM 				*propLen = reqLen + 1;
27509585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
27519585STim.Szeto@Sun.COM 			}
27529585STim.Szeto@Sun.COM 			break;
27539585STim.Szeto@Sun.COM 		case STMF_LU_PROP_SIZE:
27549585STim.Szeto@Sun.COM 			if (diskLu->luSizeValid == B_FALSE) {
27559585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
27569585STim.Szeto@Sun.COM 			}
27579585STim.Szeto@Sun.COM 			(void) snprintf(propVal, *propLen, "%llu",
27589585STim.Szeto@Sun.COM 			    (u_longlong_t)diskLu->luSize);
27599585STim.Szeto@Sun.COM 			break;
27609585STim.Szeto@Sun.COM 		case STMF_LU_PROP_ALIAS:
27619585STim.Szeto@Sun.COM 			if (diskLu->luAliasValid == B_FALSE) {
27629585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
27639585STim.Szeto@Sun.COM 			}
27649585STim.Szeto@Sun.COM 			if ((reqLen = strlcpy(propVal, diskLu->luAlias,
27659585STim.Szeto@Sun.COM 			    *propLen)) >= *propLen) {
27669585STim.Szeto@Sun.COM 				*propLen = reqLen + 1;
27679585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
27689585STim.Szeto@Sun.COM 			}
27699585STim.Szeto@Sun.COM 			break;
27709585STim.Szeto@Sun.COM 		case STMF_LU_PROP_VID:
27719585STim.Szeto@Sun.COM 			if (diskLu->vidValid == B_FALSE) {
27729585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
27739585STim.Szeto@Sun.COM 			}
27749585STim.Szeto@Sun.COM 			if (*propLen <= sizeof (diskLu->vid)) {
27759585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
27769585STim.Szeto@Sun.COM 			}
27779585STim.Szeto@Sun.COM 			bcopy(diskLu->vid, propVal, sizeof (diskLu->vid));
27789585STim.Szeto@Sun.COM 			propVal[sizeof (diskLu->vid)] = 0;
27799585STim.Szeto@Sun.COM 			break;
27809585STim.Szeto@Sun.COM 		case STMF_LU_PROP_PID:
27819585STim.Szeto@Sun.COM 			if (diskLu->pidValid == B_FALSE) {
27829585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
27839585STim.Szeto@Sun.COM 			}
27849585STim.Szeto@Sun.COM 			if (*propLen <= sizeof (diskLu->pid)) {
27859585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
27869585STim.Szeto@Sun.COM 			}
27879585STim.Szeto@Sun.COM 			bcopy(diskLu->pid, propVal, sizeof (diskLu->pid));
27889585STim.Szeto@Sun.COM 			propVal[sizeof (diskLu->pid)] = 0;
27899585STim.Szeto@Sun.COM 			break;
27909585STim.Szeto@Sun.COM 		case STMF_LU_PROP_WRITE_PROTECT:
27919585STim.Szeto@Sun.COM 			if (diskLu->writeProtectEnableValid == B_FALSE) {
27929585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
27939585STim.Szeto@Sun.COM 			}
27949585STim.Szeto@Sun.COM 			if (diskLu->writeProtectEnable) {
27959585STim.Szeto@Sun.COM 				if ((reqLen = strlcpy(propVal, "true",
27969585STim.Szeto@Sun.COM 				    *propLen)) >= *propLen) {
27979585STim.Szeto@Sun.COM 					*propLen = reqLen + 1;
27989585STim.Szeto@Sun.COM 					return (STMF_ERROR_INVALID_ARG);
27999585STim.Szeto@Sun.COM 				}
28009585STim.Szeto@Sun.COM 			} else {
28019585STim.Szeto@Sun.COM 				if ((reqLen = strlcpy(propVal, "false",
28029585STim.Szeto@Sun.COM 				    *propLen)) >= *propLen) {
28039585STim.Szeto@Sun.COM 					*propLen = reqLen + 1;
28049585STim.Szeto@Sun.COM 					return (STMF_ERROR_INVALID_ARG);
28059585STim.Szeto@Sun.COM 				}
28069585STim.Szeto@Sun.COM 			}
28079585STim.Szeto@Sun.COM 			break;
28089585STim.Szeto@Sun.COM 		case STMF_LU_PROP_WRITE_CACHE_DISABLE:
28099585STim.Szeto@Sun.COM 			if (diskLu->writebackCacheDisableValid == B_FALSE) {
28109585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
28119585STim.Szeto@Sun.COM 			}
28129585STim.Szeto@Sun.COM 			if (diskLu->writebackCacheDisable) {
28139585STim.Szeto@Sun.COM 				if ((reqLen = strlcpy(propVal, "true",
28149585STim.Szeto@Sun.COM 				    *propLen)) >= *propLen) {
28159585STim.Szeto@Sun.COM 					*propLen = reqLen + 1;
28169585STim.Szeto@Sun.COM 					return (STMF_ERROR_INVALID_ARG);
28179585STim.Szeto@Sun.COM 				}
28189585STim.Szeto@Sun.COM 			} else {
28199585STim.Szeto@Sun.COM 				if ((reqLen = strlcpy(propVal, "false",
28209585STim.Szeto@Sun.COM 				    *propLen)) >= *propLen) {
28219585STim.Szeto@Sun.COM 					*propLen = reqLen + 1;
28229585STim.Szeto@Sun.COM 					return (STMF_ERROR_INVALID_ARG);
28239585STim.Szeto@Sun.COM 				}
28249585STim.Szeto@Sun.COM 			}
28259585STim.Szeto@Sun.COM 			break;
28269585STim.Szeto@Sun.COM 		default:
28279585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NO_PROP;
28289585STim.Szeto@Sun.COM 			break;
28299585STim.Szeto@Sun.COM 	}
28309585STim.Szeto@Sun.COM 
28319585STim.Szeto@Sun.COM 	return (ret);
28329585STim.Szeto@Sun.COM }
28339585STim.Szeto@Sun.COM 
28349585STim.Szeto@Sun.COM /*
28359585STim.Szeto@Sun.COM  * setDiskProp
28369585STim.Szeto@Sun.COM  *
28379585STim.Szeto@Sun.COM  * Purpose: set properties for resource of type disk
28389585STim.Szeto@Sun.COM  *
28399585STim.Szeto@Sun.COM  * hdl - allocated luResourceImpl
28409585STim.Szeto@Sun.COM  * resourceProp - valid resource identifier
28419585STim.Szeto@Sun.COM  * propVal - valid resource value
28429585STim.Szeto@Sun.COM  */
28439585STim.Szeto@Sun.COM static int
28449585STim.Szeto@Sun.COM setDiskProp(luResourceImpl *hdl, uint32_t resourceProp, const char *propVal)
28459585STim.Szeto@Sun.COM {
28469585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
28479585STim.Szeto@Sun.COM 	int i;
28489585STim.Szeto@Sun.COM 	diskResource *diskLu = hdl->resource;
28499585STim.Szeto@Sun.COM 	unsigned long long numericProp = 0;
28509585STim.Szeto@Sun.COM 	char guidProp[LU_ASCII_GUID_SIZE + 1];
28519585STim.Szeto@Sun.COM 	char ouiProp[OUI_ASCII_SIZE + 1];
285210765SJohn.Forte@Sun.COM 	char hostIdProp[HOST_ID_ASCII_SIZE + 1];
28539585STim.Szeto@Sun.COM 	unsigned int oui[OUI_SIZE];
285410765SJohn.Forte@Sun.COM 	unsigned int hostId[HOST_ID_SIZE];
28559585STim.Szeto@Sun.COM 	unsigned int guid[LU_GUID_SIZE];
28569585STim.Szeto@Sun.COM 	int propSize;
28579585STim.Szeto@Sun.COM 
28589585STim.Szeto@Sun.COM 
28599585STim.Szeto@Sun.COM 	if (propVal == NULL) {
28609585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
28619585STim.Szeto@Sun.COM 	}
28629585STim.Szeto@Sun.COM 
28639585STim.Szeto@Sun.COM 	switch (resourceProp) {
28649585STim.Szeto@Sun.COM 		case STMF_LU_PROP_ALIAS:
28659585STim.Szeto@Sun.COM 			if (strlcpy(diskLu->luAlias, propVal,
28669585STim.Szeto@Sun.COM 			    sizeof (diskLu->luAlias)) >=
28679585STim.Szeto@Sun.COM 			    sizeof (diskLu->luAlias)) {
28689585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
28699585STim.Szeto@Sun.COM 			}
28709585STim.Szeto@Sun.COM 			diskLu->luAliasValid = B_TRUE;
28719585STim.Szeto@Sun.COM 			break;
28729585STim.Szeto@Sun.COM 		case STMF_LU_PROP_BLOCK_SIZE:
28739585STim.Szeto@Sun.COM 			(void) sscanf(propVal, "%llu", &numericProp);
28749585STim.Szeto@Sun.COM 			if (numericProp > UINT16_MAX) {
28759585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
28769585STim.Szeto@Sun.COM 			}
28779585STim.Szeto@Sun.COM 			diskLu->blkSize = numericProp;
28789585STim.Szeto@Sun.COM 			diskLu->blkSizeValid = B_TRUE;
28799585STim.Szeto@Sun.COM 			break;
28809585STim.Szeto@Sun.COM 		case STMF_LU_PROP_COMPANY_ID:
28819585STim.Szeto@Sun.COM 			if ((strlcpy(ouiProp, propVal, sizeof (ouiProp))) >=
28829585STim.Szeto@Sun.COM 			    sizeof (ouiProp)) {
28839585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
28849585STim.Szeto@Sun.COM 			}
28859585STim.Szeto@Sun.COM 			if (checkHexUpper(ouiProp) != 0) {
28869585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
28879585STim.Szeto@Sun.COM 			}
28889585STim.Szeto@Sun.COM 			(void) sscanf(ouiProp, "%2X%2X%2X",
28899585STim.Szeto@Sun.COM 			    &oui[0], &oui[1], &oui[2]);
28909585STim.Szeto@Sun.COM 
28919585STim.Szeto@Sun.COM 			diskLu->companyId = 0;
28929585STim.Szeto@Sun.COM 			diskLu->companyId += oui[0] << 16;
28939585STim.Szeto@Sun.COM 			diskLu->companyId += oui[1] << 8;
28949585STim.Szeto@Sun.COM 			diskLu->companyId += oui[2];
289510765SJohn.Forte@Sun.COM 			if (diskLu->companyId == 0) {
289610765SJohn.Forte@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
289710765SJohn.Forte@Sun.COM 			}
28989585STim.Szeto@Sun.COM 			diskLu->companyIdValid = B_TRUE;
28999585STim.Szeto@Sun.COM 			break;
290010765SJohn.Forte@Sun.COM 		case STMF_LU_PROP_HOST_ID:
290110765SJohn.Forte@Sun.COM 			if ((strlcpy(hostIdProp, propVal,
290210765SJohn.Forte@Sun.COM 			    sizeof (hostIdProp))) >= sizeof (hostIdProp)) {
290310765SJohn.Forte@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
290410765SJohn.Forte@Sun.COM 			}
290510765SJohn.Forte@Sun.COM 			if (checkHexUpper(hostIdProp) != 0) {
290610765SJohn.Forte@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
290710765SJohn.Forte@Sun.COM 			}
290810765SJohn.Forte@Sun.COM 			(void) sscanf(hostIdProp, "%2X%2X%2X%2X",
290910765SJohn.Forte@Sun.COM 			    &hostId[0], &hostId[1], &hostId[2], &hostId[3]);
291010765SJohn.Forte@Sun.COM 
291110765SJohn.Forte@Sun.COM 			diskLu->hostId = 0;
291210765SJohn.Forte@Sun.COM 			diskLu->hostId += hostId[0] << 24;
291310765SJohn.Forte@Sun.COM 			diskLu->hostId += hostId[1] << 16;
291410765SJohn.Forte@Sun.COM 			diskLu->hostId += hostId[2] << 8;
291510765SJohn.Forte@Sun.COM 			diskLu->hostId += hostId[3];
291610765SJohn.Forte@Sun.COM 			if (diskLu->hostId == 0) {
291710765SJohn.Forte@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
291810765SJohn.Forte@Sun.COM 			}
291910765SJohn.Forte@Sun.COM 			diskLu->hostIdValid = B_TRUE;
292010765SJohn.Forte@Sun.COM 			break;
29219585STim.Szeto@Sun.COM 		case STMF_LU_PROP_GUID:
29229585STim.Szeto@Sun.COM 			if (strlen(propVal) != LU_ASCII_GUID_SIZE) {
29239585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
29249585STim.Szeto@Sun.COM 			}
29259585STim.Szeto@Sun.COM 
29269585STim.Szeto@Sun.COM 			if ((strlcpy(guidProp, propVal, sizeof (guidProp))) >=
29279585STim.Szeto@Sun.COM 			    sizeof (guidProp)) {
29289585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
29299585STim.Szeto@Sun.COM 			}
29309585STim.Szeto@Sun.COM 
29319585STim.Szeto@Sun.COM 			if (checkHexUpper(guidProp) != 0) {
29329585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
29339585STim.Szeto@Sun.COM 			}
29349585STim.Szeto@Sun.COM 
29359585STim.Szeto@Sun.COM 			(void) sscanf(guidProp,
29369585STim.Szeto@Sun.COM 			    "%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X",
29379585STim.Szeto@Sun.COM 			    &guid[0], &guid[1], &guid[2], &guid[3], &guid[4],
29389585STim.Szeto@Sun.COM 			    &guid[5], &guid[6], &guid[7], &guid[8], &guid[9],
29399585STim.Szeto@Sun.COM 			    &guid[10], &guid[11], &guid[12], &guid[13],
29409585STim.Szeto@Sun.COM 			    &guid[14], &guid[15]);
29419585STim.Szeto@Sun.COM 			for (i = 0; i < sizeof (diskLu->luGuid); i++) {
29429585STim.Szeto@Sun.COM 				diskLu->luGuid[i] = guid[i];
29439585STim.Szeto@Sun.COM 			}
29449585STim.Szeto@Sun.COM 			diskLu->luGuidValid = B_TRUE;
29459585STim.Szeto@Sun.COM 			break;
29469585STim.Szeto@Sun.COM 		case STMF_LU_PROP_FILENAME:
29479585STim.Szeto@Sun.COM 			if ((strlcpy(diskLu->luDataFileName, propVal,
29489585STim.Szeto@Sun.COM 			    sizeof (diskLu->luDataFileName))) >=
29499585STim.Szeto@Sun.COM 			    sizeof (diskLu->luDataFileName)) {
29509585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
29519585STim.Szeto@Sun.COM 			}
29529585STim.Szeto@Sun.COM 			diskLu->luDataFileNameValid = B_TRUE;
29539585STim.Szeto@Sun.COM 			break;
29549585STim.Szeto@Sun.COM 		case STMF_LU_PROP_META_FILENAME:
29559585STim.Szeto@Sun.COM 			if ((strlcpy(diskLu->luMetaFileName, propVal,
29569585STim.Szeto@Sun.COM 			    sizeof (diskLu->luMetaFileName))) >=
29579585STim.Szeto@Sun.COM 			    sizeof (diskLu->luMetaFileName)) {
29589585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
29599585STim.Szeto@Sun.COM 			}
29609585STim.Szeto@Sun.COM 			diskLu->luMetaFileNameValid = B_TRUE;
29619585STim.Szeto@Sun.COM 			break;
296210113SNattuvetty.Bhavyan@Sun.COM 		case STMF_LU_PROP_MGMT_URL:
296310113SNattuvetty.Bhavyan@Sun.COM 			if ((strlcpy(diskLu->luMgmtUrl, propVal,
296410113SNattuvetty.Bhavyan@Sun.COM 			    sizeof (diskLu->luMgmtUrl))) >=
296510113SNattuvetty.Bhavyan@Sun.COM 			    sizeof (diskLu->luMgmtUrl)) {
296610113SNattuvetty.Bhavyan@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
296710113SNattuvetty.Bhavyan@Sun.COM 			}
296810113SNattuvetty.Bhavyan@Sun.COM 			diskLu->luMgmtUrlValid = B_TRUE;
296910113SNattuvetty.Bhavyan@Sun.COM 			break;
29709585STim.Szeto@Sun.COM 		case STMF_LU_PROP_PID:
29719585STim.Szeto@Sun.COM 			if ((propSize = strlen(propVal)) >
29729585STim.Szeto@Sun.COM 			    sizeof (diskLu->pid)) {
29739585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
29749585STim.Szeto@Sun.COM 			}
29759585STim.Szeto@Sun.COM 			(void) strncpy(diskLu->pid, propVal, propSize);
29769585STim.Szeto@Sun.COM 			diskLu->pidValid = B_TRUE;
29779585STim.Szeto@Sun.COM 			break;
29789585STim.Szeto@Sun.COM 		case STMF_LU_PROP_SERIAL_NUM:
29799585STim.Szeto@Sun.COM 			if ((propSize = strlen(propVal)) >
29809585STim.Szeto@Sun.COM 			    (sizeof (diskLu->serialNum) - 1)) {
29819585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
29829585STim.Szeto@Sun.COM 			}
29839585STim.Szeto@Sun.COM 			(void) strncpy(diskLu->serialNum, propVal, propSize);
29849585STim.Szeto@Sun.COM 			diskLu->serialNumValid = B_TRUE;
29859585STim.Szeto@Sun.COM 			break;
29869585STim.Szeto@Sun.COM 		case STMF_LU_PROP_SIZE:
29879585STim.Szeto@Sun.COM 			if ((niceStrToNum(propVal, &diskLu->luSize) != 0)) {
29889585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
29899585STim.Szeto@Sun.COM 			}
29909585STim.Szeto@Sun.COM 			diskLu->luSizeValid = B_TRUE;
29919585STim.Szeto@Sun.COM 			break;
29929585STim.Szeto@Sun.COM 		case STMF_LU_PROP_VID:
29939585STim.Szeto@Sun.COM 			if ((propSize = strlen(propVal)) >
29949585STim.Szeto@Sun.COM 			    sizeof (diskLu->vid)) {
29959585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
29969585STim.Szeto@Sun.COM 			}
29979585STim.Szeto@Sun.COM 			(void) strncpy(diskLu->vid, propVal, propSize);
29989585STim.Szeto@Sun.COM 			diskLu->vidValid = B_TRUE;
29999585STim.Szeto@Sun.COM 			break;
30009585STim.Szeto@Sun.COM 		case STMF_LU_PROP_WRITE_PROTECT:
30019585STim.Szeto@Sun.COM 			if (strcasecmp(propVal, "TRUE") == 0) {
30029585STim.Szeto@Sun.COM 				diskLu->writeProtectEnable = B_TRUE;
30039585STim.Szeto@Sun.COM 			} else if (strcasecmp(propVal, "FALSE") == 0) {
30049585STim.Szeto@Sun.COM 				diskLu->writeProtectEnable = B_FALSE;
30059585STim.Szeto@Sun.COM 			} else {
30069585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
30079585STim.Szeto@Sun.COM 			}
30089585STim.Szeto@Sun.COM 			diskLu->writeProtectEnableValid = B_TRUE;
30099585STim.Szeto@Sun.COM 			break;
30109585STim.Szeto@Sun.COM 		case STMF_LU_PROP_WRITE_CACHE_DISABLE:
30119585STim.Szeto@Sun.COM 			if (strcasecmp(propVal, "TRUE") == 0) {
30129585STim.Szeto@Sun.COM 				diskLu->writebackCacheDisable = B_TRUE;
30139585STim.Szeto@Sun.COM 			} else if (strcasecmp(propVal, "FALSE") == 0) {
30149585STim.Szeto@Sun.COM 				diskLu->writebackCacheDisable = B_FALSE;
30159585STim.Szeto@Sun.COM 			} else {
30169585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
30179585STim.Szeto@Sun.COM 			}
30189585STim.Szeto@Sun.COM 			diskLu->writebackCacheDisableValid = B_TRUE;
30199585STim.Szeto@Sun.COM 			break;
302010725SJohn.Forte@Sun.COM 		case STMF_LU_PROP_ACCESS_STATE:
302110725SJohn.Forte@Sun.COM 			ret = STMF_ERROR_INVALID_PROP;
302210725SJohn.Forte@Sun.COM 			break;
30239585STim.Szeto@Sun.COM 		default:
30249585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NO_PROP;
30259585STim.Szeto@Sun.COM 			break;
30269585STim.Szeto@Sun.COM 	}
30279585STim.Szeto@Sun.COM 	return (ret);
30289585STim.Szeto@Sun.COM }
30299585STim.Szeto@Sun.COM 
30309585STim.Szeto@Sun.COM static int
30319585STim.Szeto@Sun.COM checkHexUpper(char *buf)
30329585STim.Szeto@Sun.COM {
30339585STim.Szeto@Sun.COM 	int i;
30349585STim.Szeto@Sun.COM 
30359585STim.Szeto@Sun.COM 	for (i = 0; i < strlen(buf); i++) {
30369585STim.Szeto@Sun.COM 		if (isxdigit(buf[i])) {
30379585STim.Szeto@Sun.COM 			buf[i] = toupper(buf[i]);
30389585STim.Szeto@Sun.COM 			continue;
30399585STim.Szeto@Sun.COM 		}
30409585STim.Szeto@Sun.COM 		return (-1);
30419585STim.Szeto@Sun.COM 	}
30429585STim.Szeto@Sun.COM 
30439585STim.Szeto@Sun.COM 	return (0);
30449585STim.Szeto@Sun.COM }
30459585STim.Szeto@Sun.COM 
30469585STim.Szeto@Sun.COM /*
30479585STim.Szeto@Sun.COM  * Given a numeric suffix, convert the value into a number of bits that the
30489585STim.Szeto@Sun.COM  * resulting value must be shifted.
30499585STim.Szeto@Sun.COM  * Code lifted from libzfs_util.c
30509585STim.Szeto@Sun.COM  */
30519585STim.Szeto@Sun.COM static int
30529585STim.Szeto@Sun.COM strToShift(const char *buf)
30539585STim.Szeto@Sun.COM {
30549585STim.Szeto@Sun.COM 	const char *ends = "BKMGTPE";
30559585STim.Szeto@Sun.COM 	int i;
30569585STim.Szeto@Sun.COM 
30579585STim.Szeto@Sun.COM 	if (buf[0] == '\0')
30589585STim.Szeto@Sun.COM 		return (0);
30599585STim.Szeto@Sun.COM 
30609585STim.Szeto@Sun.COM 	for (i = 0; i < strlen(ends); i++) {
30619585STim.Szeto@Sun.COM 		if (toupper(buf[0]) == ends[i])
30629585STim.Szeto@Sun.COM 			return (10*i);
30639585STim.Szeto@Sun.COM 	}
30649585STim.Szeto@Sun.COM 
30659585STim.Szeto@Sun.COM 	return (-1);
30669585STim.Szeto@Sun.COM }
30679585STim.Szeto@Sun.COM 
30689585STim.Szeto@Sun.COM int
30699585STim.Szeto@Sun.COM stmfFreeLuResource(luResource hdl)
30709585STim.Szeto@Sun.COM {
30719585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
30729585STim.Szeto@Sun.COM 	if (hdl == NULL) {
30739585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
30749585STim.Szeto@Sun.COM 	}
30759585STim.Szeto@Sun.COM 
30769585STim.Szeto@Sun.COM 	luResourceImpl *hdlImpl = hdl;
30779585STim.Szeto@Sun.COM 	free(hdlImpl->resource);
30789585STim.Szeto@Sun.COM 	free(hdlImpl);
30799585STim.Szeto@Sun.COM 	return (ret);
30809585STim.Szeto@Sun.COM }
30819585STim.Szeto@Sun.COM 
30829585STim.Szeto@Sun.COM /*
30839585STim.Szeto@Sun.COM  * Convert a string of the form '100G' into a real number. Used when setting
30849585STim.Szeto@Sun.COM  * the size of a logical unit.
30859585STim.Szeto@Sun.COM  * Code lifted from libzfs_util.c
30869585STim.Szeto@Sun.COM  */
30879585STim.Szeto@Sun.COM static int
30889585STim.Szeto@Sun.COM niceStrToNum(const char *value, uint64_t *num)
30899585STim.Szeto@Sun.COM {
30909585STim.Szeto@Sun.COM 	char *end;
30919585STim.Szeto@Sun.COM 	int shift;
30929585STim.Szeto@Sun.COM 
30939585STim.Szeto@Sun.COM 	*num = 0;
30949585STim.Szeto@Sun.COM 
30959585STim.Szeto@Sun.COM 	/* Check to see if this looks like a number.  */
30969585STim.Szeto@Sun.COM 	if ((value[0] < '0' || value[0] > '9') && value[0] != '.') {
30979585STim.Szeto@Sun.COM 		return (-1);
30989585STim.Szeto@Sun.COM 	}
30999585STim.Szeto@Sun.COM 
31009585STim.Szeto@Sun.COM 	/* Rely on stroull() to process the numeric portion.  */
31019585STim.Szeto@Sun.COM 	errno = 0;
31029585STim.Szeto@Sun.COM 	*num = strtoull(value, &end, 10);
31039585STim.Szeto@Sun.COM 
31049585STim.Szeto@Sun.COM 	/*
31059585STim.Szeto@Sun.COM 	 * Check for ERANGE, which indicates that the value is too large to fit
31069585STim.Szeto@Sun.COM 	 * in a 64-bit value.
31079585STim.Szeto@Sun.COM 	 */
31089585STim.Szeto@Sun.COM 	if (errno == ERANGE) {
31099585STim.Szeto@Sun.COM 		return (-1);
31109585STim.Szeto@Sun.COM 	}
31119585STim.Szeto@Sun.COM 
31129585STim.Szeto@Sun.COM 	/*
31139585STim.Szeto@Sun.COM 	 * If we have a decimal value, then do the computation with floating
31149585STim.Szeto@Sun.COM 	 * point arithmetic.  Otherwise, use standard arithmetic.
31159585STim.Szeto@Sun.COM 	 */
31169585STim.Szeto@Sun.COM 	if (*end == '.') {
31179585STim.Szeto@Sun.COM 		double fval = strtod(value, &end);
31189585STim.Szeto@Sun.COM 
31199585STim.Szeto@Sun.COM 		if ((shift = strToShift(end)) == -1) {
31209585STim.Szeto@Sun.COM 			return (-1);
31219585STim.Szeto@Sun.COM 		}
31229585STim.Szeto@Sun.COM 
31239585STim.Szeto@Sun.COM 		fval *= pow(2, shift);
31249585STim.Szeto@Sun.COM 
31259585STim.Szeto@Sun.COM 		if (fval > UINT64_MAX) {
31269585STim.Szeto@Sun.COM 			return (-1);
31279585STim.Szeto@Sun.COM 		}
31289585STim.Szeto@Sun.COM 
31299585STim.Szeto@Sun.COM 		*num = (uint64_t)fval;
31309585STim.Szeto@Sun.COM 	} else {
31319585STim.Szeto@Sun.COM 		if ((shift = strToShift(end)) == -1) {
31329585STim.Szeto@Sun.COM 			return (-1);
31339585STim.Szeto@Sun.COM 		}
31349585STim.Szeto@Sun.COM 
31359585STim.Szeto@Sun.COM 		/* Check for overflow */
31369585STim.Szeto@Sun.COM 		if (shift >= 64 || (*num << shift) >> shift != *num) {
31379585STim.Szeto@Sun.COM 			return (-1);
31389585STim.Szeto@Sun.COM 		}
31399585STim.Szeto@Sun.COM 
31409585STim.Szeto@Sun.COM 		*num <<= shift;
31419585STim.Szeto@Sun.COM 	}
31429585STim.Szeto@Sun.COM 
31439585STim.Szeto@Sun.COM 	return (0);
31449585STim.Szeto@Sun.COM }
31459585STim.Szeto@Sun.COM 
31469585STim.Szeto@Sun.COM /*
31477836SJohn.Forte@Sun.COM  * stmfCreateTargetGroup
31487836SJohn.Forte@Sun.COM  *
31497836SJohn.Forte@Sun.COM  * Purpose: Create a local port group
31507836SJohn.Forte@Sun.COM  *
31517836SJohn.Forte@Sun.COM  * targetGroupName - name of local port group to create
31527836SJohn.Forte@Sun.COM  */
31537836SJohn.Forte@Sun.COM int
31547836SJohn.Forte@Sun.COM stmfCreateTargetGroup(stmfGroupName *targetGroupName)
31557836SJohn.Forte@Sun.COM {
31567836SJohn.Forte@Sun.COM 	int ret;
31577836SJohn.Forte@Sun.COM 	int fd;
31587836SJohn.Forte@Sun.COM 
31597836SJohn.Forte@Sun.COM 	if (targetGroupName == NULL ||
31607836SJohn.Forte@Sun.COM 	    (strnlen((char *)targetGroupName, sizeof (stmfGroupName))
31617836SJohn.Forte@Sun.COM 	    == sizeof (stmfGroupName))) {
31627836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
31637836SJohn.Forte@Sun.COM 	}
31647836SJohn.Forte@Sun.COM 
31657836SJohn.Forte@Sun.COM 	/* Check to ensure service exists */
31667836SJohn.Forte@Sun.COM 	if (psCheckService() != STMF_STATUS_SUCCESS) {
31677836SJohn.Forte@Sun.COM 		return (STMF_ERROR_SERVICE_NOT_FOUND);
31687836SJohn.Forte@Sun.COM 	}
31697836SJohn.Forte@Sun.COM 
31707836SJohn.Forte@Sun.COM 	/* call init */
31717836SJohn.Forte@Sun.COM 	ret = initializeConfig();
31727836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
31737836SJohn.Forte@Sun.COM 		return (ret);
31747836SJohn.Forte@Sun.COM 	}
31757836SJohn.Forte@Sun.COM 
31767836SJohn.Forte@Sun.COM 	/*
31777836SJohn.Forte@Sun.COM 	 * Open control node for stmf
31787836SJohn.Forte@Sun.COM 	 */
31797836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
31807836SJohn.Forte@Sun.COM 		return (ret);
31817836SJohn.Forte@Sun.COM 
31827836SJohn.Forte@Sun.COM 	/*
31837836SJohn.Forte@Sun.COM 	 * Add the group to the driver
31847836SJohn.Forte@Sun.COM 	 */
31857836SJohn.Forte@Sun.COM 	if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_TARGET_GROUP,
31867836SJohn.Forte@Sun.COM 	    targetGroupName)) != STMF_STATUS_SUCCESS) {
31877836SJohn.Forte@Sun.COM 		goto done;
31887836SJohn.Forte@Sun.COM 	}
31897836SJohn.Forte@Sun.COM 
31909585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
31919585STim.Szeto@Sun.COM 		goto done;
31929585STim.Szeto@Sun.COM 	}
31939585STim.Szeto@Sun.COM 
31947836SJohn.Forte@Sun.COM 	/*
31957836SJohn.Forte@Sun.COM 	 * If the add to the driver was successful, add it to the persistent
31967836SJohn.Forte@Sun.COM 	 * store.
31977836SJohn.Forte@Sun.COM 	 */
31987836SJohn.Forte@Sun.COM 	ret = psCreateTargetGroup((char *)targetGroupName);
31997836SJohn.Forte@Sun.COM 	switch (ret) {
32007836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
32017836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
32027836SJohn.Forte@Sun.COM 			break;
32037836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_EXISTS:
32047836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_EXISTS;
32057836SJohn.Forte@Sun.COM 			break;
32067836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
32077836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
32087836SJohn.Forte@Sun.COM 			break;
32097836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
32107836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
32117836SJohn.Forte@Sun.COM 			break;
32127836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
32137836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
32147836SJohn.Forte@Sun.COM 			break;
32157836SJohn.Forte@Sun.COM 		default:
32167836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
32177836SJohn.Forte@Sun.COM 			    "stmfCreateTargetGroup:psCreateTargetGroup"
32187836SJohn.Forte@Sun.COM 			    ":error(%d)", ret);
32197836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
32207836SJohn.Forte@Sun.COM 			break;
32217836SJohn.Forte@Sun.COM 	}
32227836SJohn.Forte@Sun.COM 
32237836SJohn.Forte@Sun.COM done:
32247836SJohn.Forte@Sun.COM 	(void) close(fd);
32257836SJohn.Forte@Sun.COM 	return (ret);
32267836SJohn.Forte@Sun.COM }
32277836SJohn.Forte@Sun.COM 
32287836SJohn.Forte@Sun.COM /*
32297836SJohn.Forte@Sun.COM  * stmfDeleteHostGroup
32307836SJohn.Forte@Sun.COM  *
32317836SJohn.Forte@Sun.COM  * Purpose: Delete an initiator or local port group
32327836SJohn.Forte@Sun.COM  *
32337836SJohn.Forte@Sun.COM  * hostGroupName - group to delete
32347836SJohn.Forte@Sun.COM  */
32357836SJohn.Forte@Sun.COM int
32367836SJohn.Forte@Sun.COM stmfDeleteHostGroup(stmfGroupName *hostGroupName)
32377836SJohn.Forte@Sun.COM {
32387836SJohn.Forte@Sun.COM 	int ret;
32397836SJohn.Forte@Sun.COM 	int fd;
32407836SJohn.Forte@Sun.COM 
32417836SJohn.Forte@Sun.COM 	if (hostGroupName == NULL) {
32427836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
32437836SJohn.Forte@Sun.COM 	}
32447836SJohn.Forte@Sun.COM 
32457836SJohn.Forte@Sun.COM 	/* Check to ensure service exists */
32467836SJohn.Forte@Sun.COM 	if (psCheckService() != STMF_STATUS_SUCCESS) {
32477836SJohn.Forte@Sun.COM 		return (STMF_ERROR_SERVICE_NOT_FOUND);
32487836SJohn.Forte@Sun.COM 	}
32497836SJohn.Forte@Sun.COM 
32507836SJohn.Forte@Sun.COM 	/* call init */
32517836SJohn.Forte@Sun.COM 	ret = initializeConfig();
32527836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
32537836SJohn.Forte@Sun.COM 		return (ret);
32547836SJohn.Forte@Sun.COM 	}
32557836SJohn.Forte@Sun.COM 
32567836SJohn.Forte@Sun.COM 	/*
32577836SJohn.Forte@Sun.COM 	 * Open control node for stmf
32587836SJohn.Forte@Sun.COM 	 */
32597836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
32607836SJohn.Forte@Sun.COM 		return (ret);
32617836SJohn.Forte@Sun.COM 
32627836SJohn.Forte@Sun.COM 	/*
32637836SJohn.Forte@Sun.COM 	 * Remove the group from the driver
32647836SJohn.Forte@Sun.COM 	 */
32657836SJohn.Forte@Sun.COM 	if ((ret = groupIoctl(fd, STMF_IOCTL_REMOVE_HOST_GROUP,
32667836SJohn.Forte@Sun.COM 	    hostGroupName)) != STMF_STATUS_SUCCESS) {
32677836SJohn.Forte@Sun.COM 		goto done;
32687836SJohn.Forte@Sun.COM 	}
32697836SJohn.Forte@Sun.COM 
32709585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
32719585STim.Szeto@Sun.COM 		goto done;
32729585STim.Szeto@Sun.COM 	}
32739585STim.Szeto@Sun.COM 
32747836SJohn.Forte@Sun.COM 	/*
32757836SJohn.Forte@Sun.COM 	 * If the remove from the driver was successful, remove it from the
32767836SJohn.Forte@Sun.COM 	 * persistent store.
32777836SJohn.Forte@Sun.COM 	 */
32787836SJohn.Forte@Sun.COM 	ret = psDeleteHostGroup((char *)hostGroupName);
32797836SJohn.Forte@Sun.COM 	switch (ret) {
32807836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
32817836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
32827836SJohn.Forte@Sun.COM 			break;
32837836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
32847836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
32857836SJohn.Forte@Sun.COM 			break;
32867836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
32877836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
32887836SJohn.Forte@Sun.COM 			break;
32897836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
32907836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
32917836SJohn.Forte@Sun.COM 			break;
32927836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
32937836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
32947836SJohn.Forte@Sun.COM 			break;
32957836SJohn.Forte@Sun.COM 		default:
32967836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
32977836SJohn.Forte@Sun.COM 			    "stmfDeleteHostGroup:psDeleteHostGroup:error(%d)",
32987836SJohn.Forte@Sun.COM 			    ret);
32997836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
33007836SJohn.Forte@Sun.COM 			break;
33017836SJohn.Forte@Sun.COM 	}
33027836SJohn.Forte@Sun.COM 
33037836SJohn.Forte@Sun.COM done:
33047836SJohn.Forte@Sun.COM 	(void) close(fd);
33057836SJohn.Forte@Sun.COM 	return (ret);
33067836SJohn.Forte@Sun.COM }
33077836SJohn.Forte@Sun.COM 
33087836SJohn.Forte@Sun.COM /*
33097836SJohn.Forte@Sun.COM  * stmfDeleteTargetGroup
33107836SJohn.Forte@Sun.COM  *
33117836SJohn.Forte@Sun.COM  * Purpose: Delete an initiator or local port group
33127836SJohn.Forte@Sun.COM  *
33137836SJohn.Forte@Sun.COM  * targetGroupName - group to delete
33147836SJohn.Forte@Sun.COM  */
33157836SJohn.Forte@Sun.COM int
33167836SJohn.Forte@Sun.COM stmfDeleteTargetGroup(stmfGroupName *targetGroupName)
33177836SJohn.Forte@Sun.COM {
33187836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
33197836SJohn.Forte@Sun.COM 	int fd;
33207836SJohn.Forte@Sun.COM 
33217836SJohn.Forte@Sun.COM 	if (targetGroupName == NULL) {
33227836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
33237836SJohn.Forte@Sun.COM 	}
33247836SJohn.Forte@Sun.COM 
33257836SJohn.Forte@Sun.COM 	/* Check to ensure service exists */
33267836SJohn.Forte@Sun.COM 	if (psCheckService() != STMF_STATUS_SUCCESS) {
33277836SJohn.Forte@Sun.COM 		return (STMF_ERROR_SERVICE_NOT_FOUND);
33287836SJohn.Forte@Sun.COM 	}
33297836SJohn.Forte@Sun.COM 
33307836SJohn.Forte@Sun.COM 	/* call init */
33317836SJohn.Forte@Sun.COM 	ret = initializeConfig();
33327836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
33337836SJohn.Forte@Sun.COM 		return (ret);
33347836SJohn.Forte@Sun.COM 	}
33357836SJohn.Forte@Sun.COM 
33367836SJohn.Forte@Sun.COM 	/*
33377836SJohn.Forte@Sun.COM 	 * Open control node for stmf
33387836SJohn.Forte@Sun.COM 	 */
33397836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
33407836SJohn.Forte@Sun.COM 		return (ret);
33417836SJohn.Forte@Sun.COM 
33427836SJohn.Forte@Sun.COM 	/*
33437836SJohn.Forte@Sun.COM 	 * Remove the group from the driver
33447836SJohn.Forte@Sun.COM 	 */
33457836SJohn.Forte@Sun.COM 	if ((ret = groupIoctl(fd, STMF_IOCTL_REMOVE_TARGET_GROUP,
33467836SJohn.Forte@Sun.COM 	    targetGroupName)) != STMF_STATUS_SUCCESS) {
33477836SJohn.Forte@Sun.COM 		goto done;
33487836SJohn.Forte@Sun.COM 	}
33497836SJohn.Forte@Sun.COM 
33509585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
33519585STim.Szeto@Sun.COM 		goto done;
33529585STim.Szeto@Sun.COM 	}
33539585STim.Szeto@Sun.COM 
33547836SJohn.Forte@Sun.COM 	/*
33557836SJohn.Forte@Sun.COM 	 * If the remove from the driver was successful, remove it from the
33567836SJohn.Forte@Sun.COM 	 * persistent store.
33577836SJohn.Forte@Sun.COM 	 */
33587836SJohn.Forte@Sun.COM 	ret = psDeleteTargetGroup((char *)targetGroupName);
33597836SJohn.Forte@Sun.COM 	switch (ret) {
33607836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
33617836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
33627836SJohn.Forte@Sun.COM 			break;
33637836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
33647836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
33657836SJohn.Forte@Sun.COM 			break;
33667836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
33677836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
33687836SJohn.Forte@Sun.COM 			break;
33697836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
33707836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
33717836SJohn.Forte@Sun.COM 			break;
33727836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
33737836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
33747836SJohn.Forte@Sun.COM 			break;
33757836SJohn.Forte@Sun.COM 		default:
33767836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
33777836SJohn.Forte@Sun.COM 			    "stmfDeleteTargetGroup:psDeleteTargetGroup"
33787836SJohn.Forte@Sun.COM 			    ":error(%d)", ret);
33797836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
33807836SJohn.Forte@Sun.COM 			break;
33817836SJohn.Forte@Sun.COM 	}
33827836SJohn.Forte@Sun.COM 
33837836SJohn.Forte@Sun.COM done:
33847836SJohn.Forte@Sun.COM 	(void) close(fd);
33857836SJohn.Forte@Sun.COM 	return (ret);
33867836SJohn.Forte@Sun.COM }
33877836SJohn.Forte@Sun.COM 
33887836SJohn.Forte@Sun.COM /*
33897836SJohn.Forte@Sun.COM  * stmfDevidFromIscsiName
33907836SJohn.Forte@Sun.COM  *
33917836SJohn.Forte@Sun.COM  * Purpose: convert an iSCSI name to an stmf devid
33927836SJohn.Forte@Sun.COM  *
33937836SJohn.Forte@Sun.COM  * iscsiName - unicode nul terminated utf-8 encoded iSCSI name
33947836SJohn.Forte@Sun.COM  * devid - on success, contains the converted iscsi name
33957836SJohn.Forte@Sun.COM  */
33967836SJohn.Forte@Sun.COM int
33977836SJohn.Forte@Sun.COM stmfDevidFromIscsiName(char *iscsiName, stmfDevid *devid)
33987836SJohn.Forte@Sun.COM {
33997836SJohn.Forte@Sun.COM 	if (devid == NULL || iscsiName == NULL)
34007836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
34017836SJohn.Forte@Sun.COM 
34027836SJohn.Forte@Sun.COM 	bzero(devid, sizeof (stmfDevid));
34037836SJohn.Forte@Sun.COM 
34047836SJohn.Forte@Sun.COM 	/* Validate size of target */
34057836SJohn.Forte@Sun.COM 	if ((devid->identLength = strlen(iscsiName)) > MAX_ISCSI_NAME ||
34067836SJohn.Forte@Sun.COM 	    devid->identLength < strlen(EUI) ||
34077836SJohn.Forte@Sun.COM 	    devid->identLength < strlen(IQN)) {
34087836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
34097836SJohn.Forte@Sun.COM 	}
34107836SJohn.Forte@Sun.COM 
34117836SJohn.Forte@Sun.COM 	if ((strncmp(iscsiName, EUI, strlen(EUI)) != 0) &&
34127836SJohn.Forte@Sun.COM 	    strncmp(iscsiName, IQN, strlen(IQN)) != 0) {
34137836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
34147836SJohn.Forte@Sun.COM 	}
34157836SJohn.Forte@Sun.COM 
34167836SJohn.Forte@Sun.COM 	/* copy UTF-8 bytes to ident */
34177836SJohn.Forte@Sun.COM 	bcopy(iscsiName, devid->ident, devid->identLength);
34187836SJohn.Forte@Sun.COM 
34197836SJohn.Forte@Sun.COM 	return (STMF_STATUS_SUCCESS);
34207836SJohn.Forte@Sun.COM }
34217836SJohn.Forte@Sun.COM 
34227836SJohn.Forte@Sun.COM /*
34237836SJohn.Forte@Sun.COM  * stmfDevidFromWwn
34247836SJohn.Forte@Sun.COM  *
34257836SJohn.Forte@Sun.COM  * Purpose: convert a WWN to an stmf devid
34267836SJohn.Forte@Sun.COM  *
34277836SJohn.Forte@Sun.COM  * wwn - 8-byte wwn identifier
34287836SJohn.Forte@Sun.COM  * devid - on success, contains the converted wwn
34297836SJohn.Forte@Sun.COM  */
34307836SJohn.Forte@Sun.COM int
34317836SJohn.Forte@Sun.COM stmfDevidFromWwn(uchar_t *wwn, stmfDevid *devid)
34327836SJohn.Forte@Sun.COM {
34337836SJohn.Forte@Sun.COM 	if (wwn == NULL || devid == NULL)
34347836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
34357836SJohn.Forte@Sun.COM 
34367836SJohn.Forte@Sun.COM 	bzero(devid, sizeof (stmfDevid));
34377836SJohn.Forte@Sun.COM 
34387836SJohn.Forte@Sun.COM 	/* Copy eui prefix */
34397836SJohn.Forte@Sun.COM 	(void) bcopy(WWN, devid->ident, strlen(WWN));
34407836SJohn.Forte@Sun.COM 
34417836SJohn.Forte@Sun.COM 	/* Convert to ASCII uppercase hexadecimal string */
34427836SJohn.Forte@Sun.COM 	(void) snprintf((char *)&devid->ident[strlen(WWN)],
34437836SJohn.Forte@Sun.COM 	    sizeof (devid->ident), "%02X%02X%02X%02X%02X%02X%02X%02X",
34447836SJohn.Forte@Sun.COM 	    wwn[0], wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]);
34457836SJohn.Forte@Sun.COM 
34467836SJohn.Forte@Sun.COM 	devid->identLength = strlen((char *)devid->ident);
34477836SJohn.Forte@Sun.COM 
34487836SJohn.Forte@Sun.COM 	return (STMF_STATUS_SUCCESS);
34497836SJohn.Forte@Sun.COM }
34507836SJohn.Forte@Sun.COM 
34517836SJohn.Forte@Sun.COM /*
34527836SJohn.Forte@Sun.COM  * stmfFreeMemory
34537836SJohn.Forte@Sun.COM  *
34547836SJohn.Forte@Sun.COM  * Purpose: Free memory allocated by this library
34557836SJohn.Forte@Sun.COM  *
34567836SJohn.Forte@Sun.COM  * memory - previously allocated pointer of memory managed by library
34577836SJohn.Forte@Sun.COM  */
34587836SJohn.Forte@Sun.COM void
34597836SJohn.Forte@Sun.COM stmfFreeMemory(void *memory)
34607836SJohn.Forte@Sun.COM {
34617836SJohn.Forte@Sun.COM 	free(memory);
34627836SJohn.Forte@Sun.COM }
34637836SJohn.Forte@Sun.COM 
34647836SJohn.Forte@Sun.COM /*
34659585STim.Szeto@Sun.COM  * get host group, target group list from stmf
34667836SJohn.Forte@Sun.COM  *
34679585STim.Szeto@Sun.COM  * groupType - HOST_GROUP, TARGET_GROUP
34687836SJohn.Forte@Sun.COM  */
34699585STim.Szeto@Sun.COM static int
34709585STim.Szeto@Sun.COM groupListIoctl(stmfGroupList **groupList, int groupType)
34719585STim.Szeto@Sun.COM {
34729585STim.Szeto@Sun.COM 	int ret;
34739585STim.Szeto@Sun.COM 	int fd;
34749585STim.Szeto@Sun.COM 	int ioctlRet;
34759585STim.Szeto@Sun.COM 	int i;
34769585STim.Szeto@Sun.COM 	int cmd;
34779585STim.Szeto@Sun.COM 	stmf_iocdata_t stmfIoctl;
34789585STim.Szeto@Sun.COM 	/* framework group list */
34799585STim.Szeto@Sun.COM 	stmf_group_name_t *iGroupList = NULL;
34809585STim.Szeto@Sun.COM 	uint32_t groupListSize;
34819585STim.Szeto@Sun.COM 
34829585STim.Szeto@Sun.COM 	if (groupList == NULL) {
34839585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
34849585STim.Szeto@Sun.COM 	}
34859585STim.Szeto@Sun.COM 
34869585STim.Szeto@Sun.COM 	if (groupType == HOST_GROUP) {
34879585STim.Szeto@Sun.COM 		cmd = STMF_IOCTL_GET_HG_LIST;
34889585STim.Szeto@Sun.COM 	} else if (groupType == TARGET_GROUP) {
34899585STim.Szeto@Sun.COM 		cmd = STMF_IOCTL_GET_TG_LIST;
34909585STim.Szeto@Sun.COM 	} else {
34919585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
34929585STim.Szeto@Sun.COM 	}
34939585STim.Szeto@Sun.COM 
34949585STim.Szeto@Sun.COM 	/* call init */
34959585STim.Szeto@Sun.COM 	ret = initializeConfig();
34969585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
34979585STim.Szeto@Sun.COM 		return (ret);
34989585STim.Szeto@Sun.COM 	}
34999585STim.Szeto@Sun.COM 
35009585STim.Szeto@Sun.COM 	/*
35019585STim.Szeto@Sun.COM 	 * Open control node for stmf
35029585STim.Szeto@Sun.COM 	 */
35039585STim.Szeto@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
35049585STim.Szeto@Sun.COM 		return (ret);
35059585STim.Szeto@Sun.COM 
35069585STim.Szeto@Sun.COM 	/*
35079585STim.Szeto@Sun.COM 	 * Allocate ioctl input buffer
35089585STim.Szeto@Sun.COM 	 */
35099585STim.Szeto@Sun.COM 	groupListSize = ALLOC_GROUP;
35109585STim.Szeto@Sun.COM 	groupListSize = groupListSize * (sizeof (stmf_group_name_t));
35119585STim.Szeto@Sun.COM 	iGroupList = (stmf_group_name_t *)calloc(1, groupListSize);
35129585STim.Szeto@Sun.COM 	if (iGroupList == NULL) {
35139585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
35149585STim.Szeto@Sun.COM 		goto done;
35159585STim.Szeto@Sun.COM 	}
35169585STim.Szeto@Sun.COM 
35179585STim.Szeto@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
35189585STim.Szeto@Sun.COM 	/*
35199585STim.Szeto@Sun.COM 	 * Issue ioctl to get the group list
35209585STim.Szeto@Sun.COM 	 */
35219585STim.Szeto@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
35229585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf_size = groupListSize;
35239585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupList;
35249585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
35259585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
35269585STim.Szeto@Sun.COM 		switch (errno) {
35279585STim.Szeto@Sun.COM 			case EBUSY:
35289585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
35299585STim.Szeto@Sun.COM 				break;
35309585STim.Szeto@Sun.COM 			case EPERM:
35319585STim.Szeto@Sun.COM 			case EACCES:
35329585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
35339585STim.Szeto@Sun.COM 				break;
35349585STim.Szeto@Sun.COM 			default:
35359585STim.Szeto@Sun.COM 				syslog(LOG_DEBUG,
35369585STim.Szeto@Sun.COM 				    "groupListIoctl:ioctl errno(%d)",
35379585STim.Szeto@Sun.COM 				    errno);
35389585STim.Szeto@Sun.COM 				ret = STMF_STATUS_ERROR;
35399585STim.Szeto@Sun.COM 				break;
35409585STim.Szeto@Sun.COM 		}
35419585STim.Szeto@Sun.COM 		goto done;
35429585STim.Szeto@Sun.COM 	}
35439585STim.Szeto@Sun.COM 	/*
35449585STim.Szeto@Sun.COM 	 * Check whether input buffer was large enough
35459585STim.Szeto@Sun.COM 	 */
35469585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_GROUP) {
35479585STim.Szeto@Sun.COM 		groupListSize = stmfIoctl.stmf_obuf_max_nentries *
35489585STim.Szeto@Sun.COM 		    sizeof (stmf_group_name_t);
35499585STim.Szeto@Sun.COM 		iGroupList = realloc(iGroupList, groupListSize);
35509585STim.Szeto@Sun.COM 		if (iGroupList == NULL) {
35519585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NOMEM;
35529585STim.Szeto@Sun.COM 			goto done;
35539585STim.Szeto@Sun.COM 		}
35549585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf_size = groupListSize;
35559585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupList;
35569585STim.Szeto@Sun.COM 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
35579585STim.Szeto@Sun.COM 		if (ioctlRet != 0) {
35589585STim.Szeto@Sun.COM 			switch (errno) {
35599585STim.Szeto@Sun.COM 				case EBUSY:
35609585STim.Szeto@Sun.COM 					ret = STMF_ERROR_BUSY;
35619585STim.Szeto@Sun.COM 					break;
35629585STim.Szeto@Sun.COM 				case EPERM:
35639585STim.Szeto@Sun.COM 				case EACCES:
35649585STim.Szeto@Sun.COM 					ret = STMF_ERROR_PERM;
35659585STim.Szeto@Sun.COM 					break;
35669585STim.Szeto@Sun.COM 				default:
35679585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
35689585STim.Szeto@Sun.COM 					    "groupListIoctl:ioctl errno(%d)",
35699585STim.Szeto@Sun.COM 					    errno);
35709585STim.Szeto@Sun.COM 					ret = STMF_STATUS_ERROR;
35719585STim.Szeto@Sun.COM 					break;
35729585STim.Szeto@Sun.COM 			}
35739585STim.Szeto@Sun.COM 			goto done;
35749585STim.Szeto@Sun.COM 		}
35759585STim.Szeto@Sun.COM 	}
35769585STim.Szeto@Sun.COM 
35779585STim.Szeto@Sun.COM 	/* allocate and copy to caller's buffer */
357810236SSrivijitha.Dugganapalli@Sun.COM 	*groupList = (stmfGroupList *)calloc(1, sizeof (stmfGroupList) +
357910236SSrivijitha.Dugganapalli@Sun.COM 	    sizeof (stmfGroupName) * stmfIoctl.stmf_obuf_nentries);
35809585STim.Szeto@Sun.COM 	if (*groupList == NULL) {
35819585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
35829585STim.Szeto@Sun.COM 		goto done;
35839585STim.Szeto@Sun.COM 	}
35849585STim.Szeto@Sun.COM 	(*groupList)->cnt = stmfIoctl.stmf_obuf_nentries;
35859585STim.Szeto@Sun.COM 	for (i = 0; i < stmfIoctl.stmf_obuf_nentries; i++) {
358610113SNattuvetty.Bhavyan@Sun.COM 		bcopy(iGroupList[i].name, (*groupList)->name[i],
35879585STim.Szeto@Sun.COM 		    sizeof (stmfGroupName));
35889585STim.Szeto@Sun.COM 	}
35899585STim.Szeto@Sun.COM 
35909585STim.Szeto@Sun.COM done:
35919585STim.Szeto@Sun.COM 	free(iGroupList);
35929585STim.Szeto@Sun.COM 	(void) close(fd);
35939585STim.Szeto@Sun.COM 	return (ret);
35949585STim.Szeto@Sun.COM }
35959585STim.Szeto@Sun.COM 
35969585STim.Szeto@Sun.COM /*
35979585STim.Szeto@Sun.COM  * get host group members, target group members from stmf
35989585STim.Szeto@Sun.COM  *
35999585STim.Szeto@Sun.COM  * groupProps - allocated on success
36009585STim.Szeto@Sun.COM  *
36019585STim.Szeto@Sun.COM  * groupType - HOST_GROUP, TARGET_GROUP
36029585STim.Szeto@Sun.COM  */
36039585STim.Szeto@Sun.COM static int
36049585STim.Szeto@Sun.COM groupMemberListIoctl(stmfGroupName *groupName, stmfGroupProperties **groupProps,
36059585STim.Szeto@Sun.COM     int groupType)
36067836SJohn.Forte@Sun.COM {
36077836SJohn.Forte@Sun.COM 	int ret;
36089585STim.Szeto@Sun.COM 	int fd;
36099585STim.Szeto@Sun.COM 	int ioctlRet;
36109585STim.Szeto@Sun.COM 	int i;
36119585STim.Szeto@Sun.COM 	int cmd;
36129585STim.Szeto@Sun.COM 	stmf_iocdata_t stmfIoctl;
36139585STim.Szeto@Sun.COM 	/* framework group list */
36149585STim.Szeto@Sun.COM 	stmf_group_name_t iGroupName;
36159585STim.Szeto@Sun.COM 	stmf_ge_ident_t *iGroupMembers;
36169585STim.Szeto@Sun.COM 	uint32_t groupListSize;
36179585STim.Szeto@Sun.COM 
36189585STim.Szeto@Sun.COM 	if (groupName == NULL) {
36199585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
36209585STim.Szeto@Sun.COM 	}
36219585STim.Szeto@Sun.COM 
36229585STim.Szeto@Sun.COM 	if (groupType == HOST_GROUP) {
36239585STim.Szeto@Sun.COM 		cmd = STMF_IOCTL_GET_HG_ENTRIES;
36249585STim.Szeto@Sun.COM 	} else if (groupType == TARGET_GROUP) {
36259585STim.Szeto@Sun.COM 		cmd = STMF_IOCTL_GET_TG_ENTRIES;
36269585STim.Szeto@Sun.COM 	} else {
36277836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
36287836SJohn.Forte@Sun.COM 	}
36297836SJohn.Forte@Sun.COM 
36309585STim.Szeto@Sun.COM 	/* call init */
36319585STim.Szeto@Sun.COM 	ret = initializeConfig();
36329585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
36339585STim.Szeto@Sun.COM 		return (ret);
36349585STim.Szeto@Sun.COM 	}
36359585STim.Szeto@Sun.COM 
36369585STim.Szeto@Sun.COM 	/*
36379585STim.Szeto@Sun.COM 	 * Open control node for stmf
36389585STim.Szeto@Sun.COM 	 */
36399585STim.Szeto@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
36409585STim.Szeto@Sun.COM 		return (ret);
36419585STim.Szeto@Sun.COM 
36429585STim.Szeto@Sun.COM 	bzero(&iGroupName, sizeof (iGroupName));
36439585STim.Szeto@Sun.COM 
36449585STim.Szeto@Sun.COM 	bcopy(groupName, &iGroupName.name, strlen((char *)groupName));
36459585STim.Szeto@Sun.COM 
36469585STim.Szeto@Sun.COM 	iGroupName.name_size = strlen((char *)groupName);
36479585STim.Szeto@Sun.COM 
36489585STim.Szeto@Sun.COM 	/*
36499585STim.Szeto@Sun.COM 	 * Allocate ioctl input buffer
36509585STim.Szeto@Sun.COM 	 */
36519585STim.Szeto@Sun.COM 	groupListSize = ALLOC_GRP_MEMBER;
36529585STim.Szeto@Sun.COM 	groupListSize = groupListSize * (sizeof (stmf_ge_ident_t));
36539585STim.Szeto@Sun.COM 	iGroupMembers = (stmf_ge_ident_t *)calloc(1, groupListSize);
36549585STim.Szeto@Sun.COM 	if (iGroupMembers == NULL) {
36559585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
36569585STim.Szeto@Sun.COM 		goto done;
36579585STim.Szeto@Sun.COM 	}
36589585STim.Szeto@Sun.COM 
36599585STim.Szeto@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
36609585STim.Szeto@Sun.COM 	/*
36619585STim.Szeto@Sun.COM 	 * Issue ioctl to get the group list
36629585STim.Szeto@Sun.COM 	 */
36639585STim.Szeto@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
36649585STim.Szeto@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&iGroupName;
36659585STim.Szeto@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (stmf_group_name_t);
36669585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf_size = groupListSize;
36679585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupMembers;
36689585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
36699585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
36709585STim.Szeto@Sun.COM 		switch (errno) {
36719585STim.Szeto@Sun.COM 			case EBUSY:
36729585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
36739585STim.Szeto@Sun.COM 				break;
36749585STim.Szeto@Sun.COM 			case EPERM:
36759585STim.Szeto@Sun.COM 			case EACCES:
36769585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
36779585STim.Szeto@Sun.COM 				break;
36789585STim.Szeto@Sun.COM 			default:
36799585STim.Szeto@Sun.COM 				syslog(LOG_DEBUG,
36809585STim.Szeto@Sun.COM 				    "groupListIoctl:ioctl errno(%d)",
36819585STim.Szeto@Sun.COM 				    errno);
36829585STim.Szeto@Sun.COM 				ret = STMF_STATUS_ERROR;
36839585STim.Szeto@Sun.COM 				break;
36849585STim.Szeto@Sun.COM 		}
36859585STim.Szeto@Sun.COM 		goto done;
36869585STim.Szeto@Sun.COM 	}
36879585STim.Szeto@Sun.COM 	/*
36889585STim.Szeto@Sun.COM 	 * Check whether input buffer was large enough
36899585STim.Szeto@Sun.COM 	 */
36909585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_GRP_MEMBER) {
36919585STim.Szeto@Sun.COM 		groupListSize = stmfIoctl.stmf_obuf_max_nentries *
36929585STim.Szeto@Sun.COM 		    sizeof (stmf_ge_ident_t);
36939585STim.Szeto@Sun.COM 		iGroupMembers = realloc(iGroupMembers, groupListSize);
36949585STim.Szeto@Sun.COM 		if (iGroupMembers == NULL) {
36959585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NOMEM;
36969585STim.Szeto@Sun.COM 			goto done;
36979585STim.Szeto@Sun.COM 		}
36989585STim.Szeto@Sun.COM 		stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&iGroupName;
36999585STim.Szeto@Sun.COM 		stmfIoctl.stmf_ibuf_size = sizeof (stmf_group_name_t);
37009585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf_size = groupListSize;
37019585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupMembers;
37029585STim.Szeto@Sun.COM 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
37039585STim.Szeto@Sun.COM 		if (ioctlRet != 0) {
37049585STim.Szeto@Sun.COM 			switch (errno) {
37059585STim.Szeto@Sun.COM 				case EBUSY:
37069585STim.Szeto@Sun.COM 					ret = STMF_ERROR_BUSY;
37079585STim.Szeto@Sun.COM 					break;
37089585STim.Szeto@Sun.COM 				case EPERM:
37099585STim.Szeto@Sun.COM 				case EACCES:
37109585STim.Szeto@Sun.COM 					ret = STMF_ERROR_PERM;
37119585STim.Szeto@Sun.COM 					break;
37129585STim.Szeto@Sun.COM 				default:
37139585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
37149585STim.Szeto@Sun.COM 					    "groupListIoctl:ioctl errno(%d)",
37159585STim.Szeto@Sun.COM 					    errno);
37169585STim.Szeto@Sun.COM 					ret = STMF_STATUS_ERROR;
37179585STim.Szeto@Sun.COM 					break;
37189585STim.Szeto@Sun.COM 			}
37199585STim.Szeto@Sun.COM 			goto done;
37209585STim.Szeto@Sun.COM 		}
37219585STim.Szeto@Sun.COM 	}
37229585STim.Szeto@Sun.COM 
37239585STim.Szeto@Sun.COM 	/* allocate and copy to caller's buffer */
37249585STim.Szeto@Sun.COM 	*groupProps = (stmfGroupProperties *)calloc(1,
372510236SSrivijitha.Dugganapalli@Sun.COM 	    sizeof (stmfGroupProperties) +
372610236SSrivijitha.Dugganapalli@Sun.COM 	    sizeof (stmfDevid) * stmfIoctl.stmf_obuf_nentries);
37279585STim.Szeto@Sun.COM 	if (*groupProps == NULL) {
37289585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
37299585STim.Szeto@Sun.COM 		goto done;
37309585STim.Szeto@Sun.COM 	}
37319585STim.Szeto@Sun.COM 	(*groupProps)->cnt = stmfIoctl.stmf_obuf_nentries;
37329585STim.Szeto@Sun.COM 	for (i = 0; i < stmfIoctl.stmf_obuf_nentries; i++) {
37339585STim.Szeto@Sun.COM 		(*groupProps)->name[i].identLength =
373410113SNattuvetty.Bhavyan@Sun.COM 		    iGroupMembers[i].ident_size;
373510113SNattuvetty.Bhavyan@Sun.COM 		bcopy(iGroupMembers[i].ident, (*groupProps)->name[i].ident,
373610113SNattuvetty.Bhavyan@Sun.COM 		    iGroupMembers[i].ident_size);
37379585STim.Szeto@Sun.COM 	}
37389585STim.Szeto@Sun.COM 
37399585STim.Szeto@Sun.COM done:
37409585STim.Szeto@Sun.COM 	free(iGroupMembers);
37419585STim.Szeto@Sun.COM 	(void) close(fd);
37429585STim.Szeto@Sun.COM 	return (ret);
37439585STim.Szeto@Sun.COM }
37449585STim.Szeto@Sun.COM 
37459585STim.Szeto@Sun.COM /*
37469585STim.Szeto@Sun.COM  * Purpose: access persistent config data for host groups and target groups
37479585STim.Szeto@Sun.COM  */
37489585STim.Szeto@Sun.COM static int
37499585STim.Szeto@Sun.COM iLoadGroupFromPs(stmfGroupList **groupList, int type)
37509585STim.Szeto@Sun.COM {
37519585STim.Szeto@Sun.COM 	int ret;
37529585STim.Szeto@Sun.COM 
37539585STim.Szeto@Sun.COM 	if (groupList == NULL) {
37549585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
37559585STim.Szeto@Sun.COM 	}
37569585STim.Szeto@Sun.COM 
37579585STim.Szeto@Sun.COM 	if (type == HOST_GROUP) {
37589585STim.Szeto@Sun.COM 		ret = psGetHostGroupList(groupList);
37599585STim.Szeto@Sun.COM 	} else if (type == TARGET_GROUP) {
37609585STim.Szeto@Sun.COM 		ret = psGetTargetGroupList(groupList);
37619585STim.Szeto@Sun.COM 	} else {
37629585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
37639585STim.Szeto@Sun.COM 	}
37647836SJohn.Forte@Sun.COM 	switch (ret) {
37657836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
37667836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
37677836SJohn.Forte@Sun.COM 			break;
37687836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
37697836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
37707836SJohn.Forte@Sun.COM 			break;
37717836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
37727836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
37737836SJohn.Forte@Sun.COM 			break;
37747836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
37757836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
37767836SJohn.Forte@Sun.COM 			break;
37777836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
37787836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
37797836SJohn.Forte@Sun.COM 			break;
37807836SJohn.Forte@Sun.COM 		default:
37817836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
37827836SJohn.Forte@Sun.COM 			    "stmfGetHostGroupList:psGetHostGroupList:error(%d)",
37837836SJohn.Forte@Sun.COM 			    ret);
37847836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
37857836SJohn.Forte@Sun.COM 			break;
37867836SJohn.Forte@Sun.COM 	}
37877836SJohn.Forte@Sun.COM 
37887836SJohn.Forte@Sun.COM 	return (ret);
37897836SJohn.Forte@Sun.COM }
37907836SJohn.Forte@Sun.COM 
37917836SJohn.Forte@Sun.COM /*
37929585STim.Szeto@Sun.COM  * stmfGetHostGroupList
37937836SJohn.Forte@Sun.COM  *
37949585STim.Szeto@Sun.COM  * Purpose: Retrieves the list of initiator group oids
37959585STim.Szeto@Sun.COM  *
37969585STim.Szeto@Sun.COM  * hostGroupList - pointer to pointer to hostGroupList structure
37979585STim.Szeto@Sun.COM  *                 on success, this contains the host group list.
37987836SJohn.Forte@Sun.COM  */
37997836SJohn.Forte@Sun.COM int
38009585STim.Szeto@Sun.COM stmfGetHostGroupList(stmfGroupList **hostGroupList)
38019585STim.Szeto@Sun.COM {
38029585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_ERROR;
38039585STim.Szeto@Sun.COM 
38049585STim.Szeto@Sun.COM 	if (hostGroupList == NULL) {
38059585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
38069585STim.Szeto@Sun.COM 	}
38079585STim.Szeto@Sun.COM 
38089585STim.Szeto@Sun.COM 	ret = groupListIoctl(hostGroupList, HOST_GROUP);
38099585STim.Szeto@Sun.COM 	return (ret);
38109585STim.Szeto@Sun.COM }
38119585STim.Szeto@Sun.COM 
38129585STim.Szeto@Sun.COM 
38139585STim.Szeto@Sun.COM /*
38149585STim.Szeto@Sun.COM  * Purpose: access persistent config data for host groups and target groups
38159585STim.Szeto@Sun.COM  */
38169585STim.Szeto@Sun.COM static int
38179585STim.Szeto@Sun.COM iLoadGroupMembersFromPs(stmfGroupName *groupName,
38189585STim.Szeto@Sun.COM     stmfGroupProperties **groupProp, int type)
38197836SJohn.Forte@Sun.COM {
38207836SJohn.Forte@Sun.COM 	int ret;
38217836SJohn.Forte@Sun.COM 
38229585STim.Szeto@Sun.COM 	if (groupName == NULL) {
38237836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
38247836SJohn.Forte@Sun.COM 	}
38257836SJohn.Forte@Sun.COM 
38269585STim.Szeto@Sun.COM 	if (type == HOST_GROUP) {
38279585STim.Szeto@Sun.COM 		ret = psGetHostGroupMemberList((char *)groupName, groupProp);
38289585STim.Szeto@Sun.COM 	} else if (type == TARGET_GROUP) {
38299585STim.Szeto@Sun.COM 		ret = psGetTargetGroupMemberList((char *)groupName, groupProp);
38309585STim.Szeto@Sun.COM 	} else {
38319585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
38329585STim.Szeto@Sun.COM 	}
38337836SJohn.Forte@Sun.COM 	switch (ret) {
38347836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
38357836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
38367836SJohn.Forte@Sun.COM 			break;
38377836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
38387836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
38397836SJohn.Forte@Sun.COM 			break;
38407836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
38417836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
38427836SJohn.Forte@Sun.COM 			break;
38437836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
38447836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
38457836SJohn.Forte@Sun.COM 			break;
38467836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
38477836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
38487836SJohn.Forte@Sun.COM 			break;
38497836SJohn.Forte@Sun.COM 		default:
38507836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
38519585STim.Szeto@Sun.COM 			    "iLoadGroupMembersFromPs:psGetHostGroupList:"
38529585STim.Szeto@Sun.COM 			    "error(%d)", ret);
38537836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
38547836SJohn.Forte@Sun.COM 			break;
38557836SJohn.Forte@Sun.COM 	}
38567836SJohn.Forte@Sun.COM 
38577836SJohn.Forte@Sun.COM 	return (ret);
38587836SJohn.Forte@Sun.COM }
38597836SJohn.Forte@Sun.COM 
38607836SJohn.Forte@Sun.COM /*
38619585STim.Szeto@Sun.COM  * stmfGetHostGroupMembers
38629585STim.Szeto@Sun.COM  *
38639585STim.Szeto@Sun.COM  * Purpose: Retrieves the group properties for a host group
38649585STim.Szeto@Sun.COM  *
38659585STim.Szeto@Sun.COM  * groupName - name of group for which to retrieve host group members.
38669585STim.Szeto@Sun.COM  * groupProp - pointer to pointer to stmfGroupProperties structure
38679585STim.Szeto@Sun.COM  *             on success, this contains the list of group members.
38689585STim.Szeto@Sun.COM  */
38699585STim.Szeto@Sun.COM int
38709585STim.Szeto@Sun.COM stmfGetHostGroupMembers(stmfGroupName *groupName,
38719585STim.Szeto@Sun.COM     stmfGroupProperties **groupProp)
38729585STim.Szeto@Sun.COM {
38739585STim.Szeto@Sun.COM 	int ret;
38749585STim.Szeto@Sun.COM 
38759585STim.Szeto@Sun.COM 	if (groupName == NULL || groupProp == NULL) {
38769585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
38779585STim.Szeto@Sun.COM 	}
38789585STim.Szeto@Sun.COM 
38799585STim.Szeto@Sun.COM 	ret = groupMemberListIoctl(groupName, groupProp, HOST_GROUP);
38809585STim.Szeto@Sun.COM 
38819585STim.Szeto@Sun.COM 	return (ret);
38829585STim.Szeto@Sun.COM }
38839585STim.Szeto@Sun.COM 
38849585STim.Szeto@Sun.COM /*
38857836SJohn.Forte@Sun.COM  * stmfGetProviderData
38867836SJohn.Forte@Sun.COM  *
38877836SJohn.Forte@Sun.COM  * Purpose: Get provider data list
38887836SJohn.Forte@Sun.COM  *
38897836SJohn.Forte@Sun.COM  * providerName - name of provider for which to retrieve the data
38907836SJohn.Forte@Sun.COM  * nvl - pointer to nvlist_t pointer which will contain the nvlist data
38917836SJohn.Forte@Sun.COM  *       retrieved.
38927836SJohn.Forte@Sun.COM  * providerType - type of provider for which to retrieve data.
38937836SJohn.Forte@Sun.COM  *		    STMF_LU_PROVIDER_TYPE
38947836SJohn.Forte@Sun.COM  *		    STMF_PORT_PROVIDER_TYPE
38957836SJohn.Forte@Sun.COM  */
38967836SJohn.Forte@Sun.COM int
38977836SJohn.Forte@Sun.COM stmfGetProviderData(char *providerName, nvlist_t **nvl, int providerType)
38987836SJohn.Forte@Sun.COM {
38997836SJohn.Forte@Sun.COM 	return (stmfGetProviderDataProt(providerName, nvl, providerType,
39007836SJohn.Forte@Sun.COM 	    NULL));
39017836SJohn.Forte@Sun.COM }
39027836SJohn.Forte@Sun.COM 
39037836SJohn.Forte@Sun.COM /*
39047836SJohn.Forte@Sun.COM  * stmfGetProviderDataProt
39057836SJohn.Forte@Sun.COM  *
39067836SJohn.Forte@Sun.COM  * Purpose: Get provider data list with token
39077836SJohn.Forte@Sun.COM  *
39087836SJohn.Forte@Sun.COM  * providerName - name of provider for which to retrieve the data
39097836SJohn.Forte@Sun.COM  * nvl - pointer to nvlist_t pointer which will contain the nvlist data
39107836SJohn.Forte@Sun.COM  *       retrieved.
39117836SJohn.Forte@Sun.COM  * providerType - type of provider for which to retrieve data.
39127836SJohn.Forte@Sun.COM  *		    STMF_LU_PROVIDER_TYPE
39137836SJohn.Forte@Sun.COM  *		    STMF_PORT_PROVIDER_TYPE
39147836SJohn.Forte@Sun.COM  * setToken - Returns the stale data token
39157836SJohn.Forte@Sun.COM  */
39167836SJohn.Forte@Sun.COM int
39177836SJohn.Forte@Sun.COM stmfGetProviderDataProt(char *providerName, nvlist_t **nvl, int providerType,
39187836SJohn.Forte@Sun.COM     uint64_t *setToken)
39197836SJohn.Forte@Sun.COM {
39207836SJohn.Forte@Sun.COM 	int ret;
39217836SJohn.Forte@Sun.COM 
39227836SJohn.Forte@Sun.COM 	if (providerName == NULL || nvl == NULL) {
39237836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
39247836SJohn.Forte@Sun.COM 	}
39257836SJohn.Forte@Sun.COM 	if (providerType != STMF_LU_PROVIDER_TYPE &&
39267836SJohn.Forte@Sun.COM 	    providerType != STMF_PORT_PROVIDER_TYPE) {
39277836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
39287836SJohn.Forte@Sun.COM 	}
39297836SJohn.Forte@Sun.COM 	/* call init */
39307836SJohn.Forte@Sun.COM 	ret = initializeConfig();
39317836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
39327836SJohn.Forte@Sun.COM 		return (ret);
39337836SJohn.Forte@Sun.COM 	}
39349585STim.Szeto@Sun.COM 	return (getProviderData(providerName, nvl, providerType, setToken));
39357836SJohn.Forte@Sun.COM }
39367836SJohn.Forte@Sun.COM 
39377836SJohn.Forte@Sun.COM /*
39387836SJohn.Forte@Sun.COM  * stmfGetProviderDataList
39397836SJohn.Forte@Sun.COM  *
39407836SJohn.Forte@Sun.COM  * Purpose: Get the list of providers currently persisting data
39417836SJohn.Forte@Sun.COM  *
39427836SJohn.Forte@Sun.COM  * providerList - pointer to pointer to an stmfProviderList structure allocated
39437836SJohn.Forte@Sun.COM  *                by the caller. Will contain the list of providers on success.
39447836SJohn.Forte@Sun.COM  */
39457836SJohn.Forte@Sun.COM int
39467836SJohn.Forte@Sun.COM stmfGetProviderDataList(stmfProviderList **providerList)
39477836SJohn.Forte@Sun.COM {
39487836SJohn.Forte@Sun.COM 	int ret;
39497836SJohn.Forte@Sun.COM 
39507836SJohn.Forte@Sun.COM 	ret = psGetProviderDataList(providerList);
39517836SJohn.Forte@Sun.COM 	switch (ret) {
39527836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
39537836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
39547836SJohn.Forte@Sun.COM 			break;
39557836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
39567836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
39577836SJohn.Forte@Sun.COM 			break;
39587836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
39597836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
39607836SJohn.Forte@Sun.COM 			break;
39617836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
39627836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
39637836SJohn.Forte@Sun.COM 			break;
39647836SJohn.Forte@Sun.COM 		default:
39657836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
39667836SJohn.Forte@Sun.COM 			    "stmfGetProviderDataList:psGetProviderDataList"
39677836SJohn.Forte@Sun.COM 			    ":error(%d)", ret);
39687836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
39697836SJohn.Forte@Sun.COM 			break;
39707836SJohn.Forte@Sun.COM 	}
39717836SJohn.Forte@Sun.COM 
39727836SJohn.Forte@Sun.COM 	return (ret);
39737836SJohn.Forte@Sun.COM }
39747836SJohn.Forte@Sun.COM 
39757836SJohn.Forte@Sun.COM 
39767836SJohn.Forte@Sun.COM /*
39777836SJohn.Forte@Sun.COM  * stmfGetSessionList
39787836SJohn.Forte@Sun.COM  *
39797836SJohn.Forte@Sun.COM  * Purpose: Retrieves the session list for a target (devid)
39807836SJohn.Forte@Sun.COM  *
39817836SJohn.Forte@Sun.COM  * devid - devid of target for which to retrieve session information.
39827836SJohn.Forte@Sun.COM  * sessionList - pointer to pointer to stmfSessionList structure
39837836SJohn.Forte@Sun.COM  *             on success, this contains the list of initiator sessions.
39847836SJohn.Forte@Sun.COM  */
39857836SJohn.Forte@Sun.COM int
39867836SJohn.Forte@Sun.COM stmfGetSessionList(stmfDevid *devid, stmfSessionList **sessionList)
39877836SJohn.Forte@Sun.COM {
39887836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
39897836SJohn.Forte@Sun.COM 	int fd;
39907836SJohn.Forte@Sun.COM 	int ioctlRet;
39917836SJohn.Forte@Sun.COM 	int cmd = STMF_IOCTL_SESSION_LIST;
39927836SJohn.Forte@Sun.COM 	int i;
39937836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
399410261SCharles.Ting@Sun.COM 	slist_scsi_session_t *fSessionList, *fSessionListP = NULL;
39957836SJohn.Forte@Sun.COM 	uint8_t ident[260];
39967836SJohn.Forte@Sun.COM 	uint32_t fSessionListSize;
39977836SJohn.Forte@Sun.COM 
39987836SJohn.Forte@Sun.COM 	if (sessionList == NULL || devid == NULL) {
39997836SJohn.Forte@Sun.COM 		ret = STMF_ERROR_INVALID_ARG;
40007836SJohn.Forte@Sun.COM 	}
40017836SJohn.Forte@Sun.COM 
40027836SJohn.Forte@Sun.COM 	/* call init */
40037836SJohn.Forte@Sun.COM 	ret = initializeConfig();
40047836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
40057836SJohn.Forte@Sun.COM 		return (ret);
40067836SJohn.Forte@Sun.COM 	}
40077836SJohn.Forte@Sun.COM 
40087836SJohn.Forte@Sun.COM 	/*
40097836SJohn.Forte@Sun.COM 	 * Open control node for stmf
40107836SJohn.Forte@Sun.COM 	 */
40117836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
40127836SJohn.Forte@Sun.COM 		return (ret);
40137836SJohn.Forte@Sun.COM 
40147836SJohn.Forte@Sun.COM 	/*
40157836SJohn.Forte@Sun.COM 	 * Allocate ioctl input buffer
40167836SJohn.Forte@Sun.COM 	 */
40179585STim.Szeto@Sun.COM 	fSessionListSize = ALLOC_SESSION;
40187836SJohn.Forte@Sun.COM 	fSessionListSize = fSessionListSize * (sizeof (slist_scsi_session_t));
40197836SJohn.Forte@Sun.COM 	fSessionList = (slist_scsi_session_t *)calloc(1, fSessionListSize);
402010261SCharles.Ting@Sun.COM 	fSessionListP = fSessionList;
40217836SJohn.Forte@Sun.COM 	if (fSessionList == NULL) {
402210261SCharles.Ting@Sun.COM 		ret = STMF_ERROR_NOMEM;
402310261SCharles.Ting@Sun.COM 		goto done;
40247836SJohn.Forte@Sun.COM 	}
40257836SJohn.Forte@Sun.COM 
40267836SJohn.Forte@Sun.COM 	ident[IDENT_LENGTH_BYTE] = devid->identLength;
40277836SJohn.Forte@Sun.COM 	bcopy(&(devid->ident), &ident[IDENT_LENGTH_BYTE + 1],
40287836SJohn.Forte@Sun.COM 	    devid->identLength);
40297836SJohn.Forte@Sun.COM 
40307836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
40317836SJohn.Forte@Sun.COM 	/*
40327836SJohn.Forte@Sun.COM 	 * Issue ioctl to get the session list
40337836SJohn.Forte@Sun.COM 	 */
40347836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
40357836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ident;
40367836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (ident);
40377836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = fSessionListSize;
40387836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fSessionList;
40397836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
40407836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
40417836SJohn.Forte@Sun.COM 		switch (errno) {
40427836SJohn.Forte@Sun.COM 			case EBUSY:
40437836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
40447836SJohn.Forte@Sun.COM 				break;
40459585STim.Szeto@Sun.COM 			case EPERM:
40467836SJohn.Forte@Sun.COM 			case EACCES:
40477836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
40487836SJohn.Forte@Sun.COM 				break;
40497836SJohn.Forte@Sun.COM 			default:
40507836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
40517836SJohn.Forte@Sun.COM 				    "stmfGetSessionList:ioctl errno(%d)",
40527836SJohn.Forte@Sun.COM 				    errno);
40537836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
40547836SJohn.Forte@Sun.COM 				break;
40557836SJohn.Forte@Sun.COM 		}
40567836SJohn.Forte@Sun.COM 		goto done;
40577836SJohn.Forte@Sun.COM 	}
40587836SJohn.Forte@Sun.COM 	/*
40597836SJohn.Forte@Sun.COM 	 * Check whether input buffer was large enough
40607836SJohn.Forte@Sun.COM 	 */
40619585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_SESSION) {
40627836SJohn.Forte@Sun.COM 		fSessionListSize = stmfIoctl.stmf_obuf_max_nentries *
40637836SJohn.Forte@Sun.COM 		    sizeof (slist_scsi_session_t);
40647836SJohn.Forte@Sun.COM 		fSessionList = realloc(fSessionList, fSessionListSize);
40657836SJohn.Forte@Sun.COM 		if (fSessionList == NULL) {
406610261SCharles.Ting@Sun.COM 			ret = STMF_ERROR_NOMEM;
406710261SCharles.Ting@Sun.COM 			goto done;
40687836SJohn.Forte@Sun.COM 		}
406910261SCharles.Ting@Sun.COM 		fSessionListP = fSessionList;
40707836SJohn.Forte@Sun.COM 		stmfIoctl.stmf_obuf_size = fSessionListSize;
40717836SJohn.Forte@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fSessionList;
40727836SJohn.Forte@Sun.COM 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
40737836SJohn.Forte@Sun.COM 		if (ioctlRet != 0) {
40747836SJohn.Forte@Sun.COM 			switch (errno) {
40757836SJohn.Forte@Sun.COM 				case EBUSY:
40767836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_BUSY;
40777836SJohn.Forte@Sun.COM 					break;
40789585STim.Szeto@Sun.COM 				case EPERM:
40797836SJohn.Forte@Sun.COM 				case EACCES:
40807836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_PERM;
40817836SJohn.Forte@Sun.COM 					break;
40827836SJohn.Forte@Sun.COM 				default:
40837836SJohn.Forte@Sun.COM 					syslog(LOG_DEBUG,
40847836SJohn.Forte@Sun.COM 					    "stmfGetSessionList:ioctl "
40857836SJohn.Forte@Sun.COM 					    "errno(%d)", errno);
40867836SJohn.Forte@Sun.COM 					ret = STMF_STATUS_ERROR;
40877836SJohn.Forte@Sun.COM 					break;
40887836SJohn.Forte@Sun.COM 			}
40897836SJohn.Forte@Sun.COM 			goto done;
40907836SJohn.Forte@Sun.COM 		}
40917836SJohn.Forte@Sun.COM 	}
40927836SJohn.Forte@Sun.COM 
40937836SJohn.Forte@Sun.COM 	/*
40947836SJohn.Forte@Sun.COM 	 * allocate caller's buffer with the final size
40957836SJohn.Forte@Sun.COM 	 */
40967836SJohn.Forte@Sun.COM 	*sessionList = (stmfSessionList *)calloc(1, sizeof (stmfSessionList) +
40977836SJohn.Forte@Sun.COM 	    stmfIoctl.stmf_obuf_max_nentries * sizeof (stmfSession));
40987836SJohn.Forte@Sun.COM 	if (*sessionList == NULL) {
40997836SJohn.Forte@Sun.COM 		ret = STMF_ERROR_NOMEM;
41007836SJohn.Forte@Sun.COM 		free(sessionList);
41017836SJohn.Forte@Sun.COM 		goto done;
41027836SJohn.Forte@Sun.COM 	}
41037836SJohn.Forte@Sun.COM 
41047836SJohn.Forte@Sun.COM 	(*sessionList)->cnt = stmfIoctl.stmf_obuf_max_nentries;
41057836SJohn.Forte@Sun.COM 
41067836SJohn.Forte@Sun.COM 	/*
41077836SJohn.Forte@Sun.COM 	 * copy session info to caller's buffer
41087836SJohn.Forte@Sun.COM 	 */
41097836SJohn.Forte@Sun.COM 	for (i = 0; i < (*sessionList)->cnt; i++) {
41107836SJohn.Forte@Sun.COM 		(*sessionList)->session[i].initiator.identLength =
41117836SJohn.Forte@Sun.COM 		    fSessionList->initiator[IDENT_LENGTH_BYTE];
41127836SJohn.Forte@Sun.COM 		bcopy(&(fSessionList->initiator[IDENT_LENGTH_BYTE + 1]),
41137836SJohn.Forte@Sun.COM 		    (*sessionList)->session[i].initiator.ident,
41147836SJohn.Forte@Sun.COM 		    STMF_IDENT_LENGTH);
41157836SJohn.Forte@Sun.COM 		bcopy(&(fSessionList->alias),
41167836SJohn.Forte@Sun.COM 		    &((*sessionList)->session[i].alias),
41177836SJohn.Forte@Sun.COM 		    sizeof ((*sessionList)->session[i].alias));
41187836SJohn.Forte@Sun.COM 		bcopy(&(fSessionList++->creation_time),
41197836SJohn.Forte@Sun.COM 		    &((*sessionList)->session[i].creationTime),
41207836SJohn.Forte@Sun.COM 		    sizeof (time_t));
41217836SJohn.Forte@Sun.COM 	}
41227836SJohn.Forte@Sun.COM done:
41237836SJohn.Forte@Sun.COM 	(void) close(fd);
412410261SCharles.Ting@Sun.COM 	free(fSessionListP);
41257836SJohn.Forte@Sun.COM 	return (ret);
41267836SJohn.Forte@Sun.COM }
41277836SJohn.Forte@Sun.COM 
41287836SJohn.Forte@Sun.COM /*
41297836SJohn.Forte@Sun.COM  * stmfGetTargetGroupList
41307836SJohn.Forte@Sun.COM  *
41317836SJohn.Forte@Sun.COM  * Purpose: Retrieves the list of target groups
41327836SJohn.Forte@Sun.COM  *
41337836SJohn.Forte@Sun.COM  * targetGroupList - pointer to a pointer to an stmfGroupList structure. On
41347836SJohn.Forte@Sun.COM  *		     success, it contains the list of target groups.
41357836SJohn.Forte@Sun.COM  */
41367836SJohn.Forte@Sun.COM int
41377836SJohn.Forte@Sun.COM stmfGetTargetGroupList(stmfGroupList **targetGroupList)
41387836SJohn.Forte@Sun.COM {
41397836SJohn.Forte@Sun.COM 	int ret;
41407836SJohn.Forte@Sun.COM 
41417836SJohn.Forte@Sun.COM 	if (targetGroupList == NULL) {
41427836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
41437836SJohn.Forte@Sun.COM 	}
41447836SJohn.Forte@Sun.COM 
41459585STim.Szeto@Sun.COM 	ret = groupListIoctl(targetGroupList, TARGET_GROUP);
41467836SJohn.Forte@Sun.COM 	return (ret);
41477836SJohn.Forte@Sun.COM }
41487836SJohn.Forte@Sun.COM 
41497836SJohn.Forte@Sun.COM /*
41507836SJohn.Forte@Sun.COM  * stmfGetTargetGroupMembers
41517836SJohn.Forte@Sun.COM  *
41527836SJohn.Forte@Sun.COM  * Purpose: Retrieves the group members for a target group
41537836SJohn.Forte@Sun.COM  *
41547836SJohn.Forte@Sun.COM  * groupName - name of target group for which to retrieve members.
41557836SJohn.Forte@Sun.COM  * groupProp - pointer to pointer to stmfGroupProperties structure
41567836SJohn.Forte@Sun.COM  *             on success, this contains the list of group members.
41577836SJohn.Forte@Sun.COM  */
41587836SJohn.Forte@Sun.COM int
41597836SJohn.Forte@Sun.COM stmfGetTargetGroupMembers(stmfGroupName *groupName,
41607836SJohn.Forte@Sun.COM     stmfGroupProperties **groupProp)
41617836SJohn.Forte@Sun.COM {
41627836SJohn.Forte@Sun.COM 	int ret;
41637836SJohn.Forte@Sun.COM 
41647836SJohn.Forte@Sun.COM 	if (groupName == NULL || groupProp == NULL) {
41657836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
41667836SJohn.Forte@Sun.COM 	}
41677836SJohn.Forte@Sun.COM 
41689585STim.Szeto@Sun.COM 	ret = groupMemberListIoctl(groupName, groupProp, TARGET_GROUP);
41697836SJohn.Forte@Sun.COM 
41707836SJohn.Forte@Sun.COM 	return (ret);
41717836SJohn.Forte@Sun.COM }
41727836SJohn.Forte@Sun.COM 
41737836SJohn.Forte@Sun.COM /*
41747836SJohn.Forte@Sun.COM  * stmfGetTargetList
41757836SJohn.Forte@Sun.COM  *
41767836SJohn.Forte@Sun.COM  * Purpose: Retrieves the list of target ports
41777836SJohn.Forte@Sun.COM  *
41787836SJohn.Forte@Sun.COM  * targetList - pointer to a pointer to an stmfDevidList structure.
41797836SJohn.Forte@Sun.COM  *		    On success, it contains the list of local ports (target).
41807836SJohn.Forte@Sun.COM  */
41817836SJohn.Forte@Sun.COM int
41827836SJohn.Forte@Sun.COM stmfGetTargetList(stmfDevidList **targetList)
41837836SJohn.Forte@Sun.COM {
41847836SJohn.Forte@Sun.COM 	int ret;
41857836SJohn.Forte@Sun.COM 	int fd;
41867836SJohn.Forte@Sun.COM 	int ioctlRet;
41877836SJohn.Forte@Sun.COM 	int i;
41887836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
41897836SJohn.Forte@Sun.COM 	/* framework target port list */
41909585STim.Szeto@Sun.COM 	slist_target_port_t *fTargetList, *fTargetListP = NULL;
41917836SJohn.Forte@Sun.COM 	uint32_t fTargetListSize;
41927836SJohn.Forte@Sun.COM 
41937836SJohn.Forte@Sun.COM 	if (targetList == NULL) {
41947836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
41957836SJohn.Forte@Sun.COM 	}
41967836SJohn.Forte@Sun.COM 
41977836SJohn.Forte@Sun.COM 	/* call init */
41987836SJohn.Forte@Sun.COM 	ret = initializeConfig();
41997836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
42007836SJohn.Forte@Sun.COM 		return (ret);
42017836SJohn.Forte@Sun.COM 	}
42027836SJohn.Forte@Sun.COM 
42037836SJohn.Forte@Sun.COM 	/*
42047836SJohn.Forte@Sun.COM 	 * Open control node for stmf
42057836SJohn.Forte@Sun.COM 	 */
42067836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
42077836SJohn.Forte@Sun.COM 		return (ret);
42087836SJohn.Forte@Sun.COM 
42097836SJohn.Forte@Sun.COM 	/*
42107836SJohn.Forte@Sun.COM 	 * Allocate ioctl input buffer
42117836SJohn.Forte@Sun.COM 	 */
42129585STim.Szeto@Sun.COM 	fTargetListSize = ALLOC_TARGET_PORT * sizeof (slist_target_port_t);
42138252SJohn.Forte@Sun.COM 	fTargetListP = fTargetList =
42148252SJohn.Forte@Sun.COM 	    (slist_target_port_t *)calloc(1, fTargetListSize);
42157836SJohn.Forte@Sun.COM 	if (fTargetList == NULL) {
42169585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
42177836SJohn.Forte@Sun.COM 		goto done;
42187836SJohn.Forte@Sun.COM 	}
42197836SJohn.Forte@Sun.COM 
42207836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
42217836SJohn.Forte@Sun.COM 	/*
42228252SJohn.Forte@Sun.COM 	 * Issue ioctl to retrieve target list
42237836SJohn.Forte@Sun.COM 	 */
42247836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
42257836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = fTargetListSize;
42267836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fTargetList;
42277836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_TARGET_PORT_LIST, &stmfIoctl);
42287836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
42297836SJohn.Forte@Sun.COM 		switch (errno) {
42307836SJohn.Forte@Sun.COM 			case EBUSY:
42317836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
42327836SJohn.Forte@Sun.COM 				break;
42339585STim.Szeto@Sun.COM 			case EPERM:
42347836SJohn.Forte@Sun.COM 			case EACCES:
42357836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
42367836SJohn.Forte@Sun.COM 				break;
42377836SJohn.Forte@Sun.COM 			default:
42387836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
42397836SJohn.Forte@Sun.COM 				    "stmfGetTargetList:ioctl errno(%d)", errno);
42407836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
42417836SJohn.Forte@Sun.COM 				break;
42427836SJohn.Forte@Sun.COM 		}
42437836SJohn.Forte@Sun.COM 		goto done;
42447836SJohn.Forte@Sun.COM 	}
42457836SJohn.Forte@Sun.COM 	/*
42467836SJohn.Forte@Sun.COM 	 * Check whether input buffer was large enough
42477836SJohn.Forte@Sun.COM 	 */
42489585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_TARGET_PORT) {
42497836SJohn.Forte@Sun.COM 		fTargetListSize = stmfIoctl.stmf_obuf_max_nentries *
42508116SJohn.Forte@Sun.COM 		    sizeof (slist_target_port_t);
42518252SJohn.Forte@Sun.COM 		fTargetListP = fTargetList =
42528252SJohn.Forte@Sun.COM 		    realloc(fTargetList, fTargetListSize);
42537836SJohn.Forte@Sun.COM 		if (fTargetList == NULL) {
42549585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NOMEM;
42559585STim.Szeto@Sun.COM 			goto done;
42567836SJohn.Forte@Sun.COM 		}
42577836SJohn.Forte@Sun.COM 		stmfIoctl.stmf_obuf_size = fTargetListSize;
42587836SJohn.Forte@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fTargetList;
42597836SJohn.Forte@Sun.COM 		ioctlRet = ioctl(fd, STMF_IOCTL_TARGET_PORT_LIST,
42607836SJohn.Forte@Sun.COM 		    &stmfIoctl);
42617836SJohn.Forte@Sun.COM 		if (ioctlRet != 0) {
42627836SJohn.Forte@Sun.COM 			switch (errno) {
42637836SJohn.Forte@Sun.COM 				case EBUSY:
42647836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_BUSY;
42657836SJohn.Forte@Sun.COM 					break;
42669585STim.Szeto@Sun.COM 				case EPERM:
42677836SJohn.Forte@Sun.COM 				case EACCES:
42687836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_PERM;
42697836SJohn.Forte@Sun.COM 					break;
42707836SJohn.Forte@Sun.COM 				default:
42717836SJohn.Forte@Sun.COM 					syslog(LOG_DEBUG,
42727836SJohn.Forte@Sun.COM 					    "stmfGetTargetList:ioctl errno(%d)",
42737836SJohn.Forte@Sun.COM 					    errno);
42747836SJohn.Forte@Sun.COM 					ret = STMF_STATUS_ERROR;
42757836SJohn.Forte@Sun.COM 					break;
42767836SJohn.Forte@Sun.COM 			}
42777836SJohn.Forte@Sun.COM 			goto done;
42787836SJohn.Forte@Sun.COM 		}
42797836SJohn.Forte@Sun.COM 	}
42807836SJohn.Forte@Sun.COM 
42817836SJohn.Forte@Sun.COM 	*targetList = (stmfDevidList *)calloc(1,
42827836SJohn.Forte@Sun.COM 	    stmfIoctl.stmf_obuf_max_nentries * sizeof (stmfDevid) +
42837836SJohn.Forte@Sun.COM 	    sizeof (stmfDevidList));
42849585STim.Szeto@Sun.COM 	if (*targetList == NULL) {
42859585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
42869585STim.Szeto@Sun.COM 		goto done;
42879585STim.Szeto@Sun.COM 	}
42887836SJohn.Forte@Sun.COM 
42897836SJohn.Forte@Sun.COM 	(*targetList)->cnt = stmfIoctl.stmf_obuf_max_nentries;
42907836SJohn.Forte@Sun.COM 	for (i = 0; i < stmfIoctl.stmf_obuf_max_nentries; i++, fTargetList++) {
42917836SJohn.Forte@Sun.COM 		(*targetList)->devid[i].identLength =
42927836SJohn.Forte@Sun.COM 		    fTargetList->target[IDENT_LENGTH_BYTE];
42937836SJohn.Forte@Sun.COM 		bcopy(&fTargetList->target[IDENT_LENGTH_BYTE + 1],
42947836SJohn.Forte@Sun.COM 		    &(*targetList)->devid[i].ident,
42957836SJohn.Forte@Sun.COM 		    fTargetList->target[IDENT_LENGTH_BYTE]);
42967836SJohn.Forte@Sun.COM 	}
42977836SJohn.Forte@Sun.COM 
42987836SJohn.Forte@Sun.COM done:
42997836SJohn.Forte@Sun.COM 	(void) close(fd);
43008252SJohn.Forte@Sun.COM 	free(fTargetListP);
43017836SJohn.Forte@Sun.COM 	return (ret);
43027836SJohn.Forte@Sun.COM }
43037836SJohn.Forte@Sun.COM 
43047836SJohn.Forte@Sun.COM /*
43057836SJohn.Forte@Sun.COM  * stmfGetTargetProperties
43067836SJohn.Forte@Sun.COM  *
43077836SJohn.Forte@Sun.COM  * Purpose:  Retrieves the properties for a logical unit
43087836SJohn.Forte@Sun.COM  *
43097836SJohn.Forte@Sun.COM  * devid - devid of the target for which to retrieve properties
43107836SJohn.Forte@Sun.COM  * targetProps - pointer to an stmfTargetProperties structure.
43117836SJohn.Forte@Sun.COM  *		On success, it contains the target properties for
43127836SJohn.Forte@Sun.COM  *		the specified devid.
43137836SJohn.Forte@Sun.COM  */
43147836SJohn.Forte@Sun.COM int
43157836SJohn.Forte@Sun.COM stmfGetTargetProperties(stmfDevid *devid, stmfTargetProperties *targetProps)
43167836SJohn.Forte@Sun.COM {
43177836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
43187836SJohn.Forte@Sun.COM 	int fd;
43197836SJohn.Forte@Sun.COM 	int ioctlRet;
43207836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
43217836SJohn.Forte@Sun.COM 	sioc_target_port_props_t targetProperties;
432210725SJohn.Forte@Sun.COM 	scsi_devid_desc_t *scsiDevid;
43237836SJohn.Forte@Sun.COM 
43247836SJohn.Forte@Sun.COM 	if (devid == NULL || targetProps == NULL) {
43257836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
43267836SJohn.Forte@Sun.COM 	}
43277836SJohn.Forte@Sun.COM 
43287836SJohn.Forte@Sun.COM 	/* call init */
43297836SJohn.Forte@Sun.COM 	ret = initializeConfig();
43307836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
43317836SJohn.Forte@Sun.COM 		return (ret);
43327836SJohn.Forte@Sun.COM 	}
43337836SJohn.Forte@Sun.COM 
43347836SJohn.Forte@Sun.COM 	/*
43357836SJohn.Forte@Sun.COM 	 * Open control node for stmf
43367836SJohn.Forte@Sun.COM 	 */
43377836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
43387836SJohn.Forte@Sun.COM 		return (ret);
43397836SJohn.Forte@Sun.COM 
43407836SJohn.Forte@Sun.COM 	targetProperties.tgt_id[IDENT_LENGTH_BYTE] = devid->identLength;
43417836SJohn.Forte@Sun.COM 	bcopy(&(devid->ident), &targetProperties.tgt_id[IDENT_LENGTH_BYTE + 1],
43427836SJohn.Forte@Sun.COM 	    devid->identLength);
43437836SJohn.Forte@Sun.COM 
43447836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
43457836SJohn.Forte@Sun.COM 	/*
43467836SJohn.Forte@Sun.COM 	 * Issue ioctl to add to the host group
43477836SJohn.Forte@Sun.COM 	 */
43487836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
43497836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (targetProperties.tgt_id);
43507836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&targetProperties.tgt_id;
43517836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&targetProperties;
43527836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = sizeof (targetProperties);
43537836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_GET_TARGET_PORT_PROPERTIES,
43547836SJohn.Forte@Sun.COM 	    &stmfIoctl);
43557836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
43567836SJohn.Forte@Sun.COM 		switch (errno) {
43577836SJohn.Forte@Sun.COM 			case EBUSY:
43587836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
43597836SJohn.Forte@Sun.COM 				break;
43609585STim.Szeto@Sun.COM 			case EPERM:
43617836SJohn.Forte@Sun.COM 			case EACCES:
43627836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
43637836SJohn.Forte@Sun.COM 				break;
43647836SJohn.Forte@Sun.COM 			case ENOENT:
43657836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
43667836SJohn.Forte@Sun.COM 				break;
43677836SJohn.Forte@Sun.COM 			default:
43687836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
43697836SJohn.Forte@Sun.COM 				    "stmfGetTargetProperties:ioctl errno(%d)",
43707836SJohn.Forte@Sun.COM 				    errno);
43717836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
43727836SJohn.Forte@Sun.COM 				break;
43737836SJohn.Forte@Sun.COM 		}
43747836SJohn.Forte@Sun.COM 		goto done;
43757836SJohn.Forte@Sun.COM 	}
43767836SJohn.Forte@Sun.COM 
43777836SJohn.Forte@Sun.COM 	bcopy(targetProperties.tgt_provider_name, targetProps->providerName,
43787836SJohn.Forte@Sun.COM 	    sizeof (targetProperties.tgt_provider_name));
43797836SJohn.Forte@Sun.COM 	if (targetProperties.tgt_state == STMF_STATE_ONLINE) {
43807836SJohn.Forte@Sun.COM 		targetProps->status = STMF_TARGET_PORT_ONLINE;
43817836SJohn.Forte@Sun.COM 	} else if (targetProperties.tgt_state == STMF_STATE_OFFLINE) {
43827836SJohn.Forte@Sun.COM 		targetProps->status = STMF_TARGET_PORT_OFFLINE;
43837836SJohn.Forte@Sun.COM 	} else if (targetProperties.tgt_state == STMF_STATE_ONLINING) {
43847836SJohn.Forte@Sun.COM 		targetProps->status = STMF_TARGET_PORT_ONLINING;
43857836SJohn.Forte@Sun.COM 	} else if (targetProperties.tgt_state == STMF_STATE_OFFLINING) {
43867836SJohn.Forte@Sun.COM 		targetProps->status = STMF_TARGET_PORT_OFFLINING;
43877836SJohn.Forte@Sun.COM 	}
43887836SJohn.Forte@Sun.COM 	bcopy(targetProperties.tgt_alias, targetProps->alias,
43897836SJohn.Forte@Sun.COM 	    sizeof (targetProps->alias));
439010725SJohn.Forte@Sun.COM 
439110725SJohn.Forte@Sun.COM 	scsiDevid = (scsi_devid_desc_t *)&targetProperties.tgt_id;
439210725SJohn.Forte@Sun.COM 	targetProps->protocol = scsiDevid->protocol_id;
439310725SJohn.Forte@Sun.COM 
43947836SJohn.Forte@Sun.COM done:
43957836SJohn.Forte@Sun.COM 	(void) close(fd);
43967836SJohn.Forte@Sun.COM 	return (ret);
43977836SJohn.Forte@Sun.COM }
43987836SJohn.Forte@Sun.COM 
43997836SJohn.Forte@Sun.COM /*
44007836SJohn.Forte@Sun.COM  * stmfGetLogicalUnitList
44017836SJohn.Forte@Sun.COM  *
44027836SJohn.Forte@Sun.COM  * Purpose: Retrieves list of logical unit Object IDs
44037836SJohn.Forte@Sun.COM  *
44047836SJohn.Forte@Sun.COM  * luList - pointer to a pointer to a stmfGuidList structure. On success,
44057836SJohn.Forte@Sun.COM  *          it contains the list of logical unit guids.
44067836SJohn.Forte@Sun.COM  *
44077836SJohn.Forte@Sun.COM  */
44087836SJohn.Forte@Sun.COM int
44097836SJohn.Forte@Sun.COM stmfGetLogicalUnitList(stmfGuidList **luList)
44107836SJohn.Forte@Sun.COM {
44117836SJohn.Forte@Sun.COM 	int ret;
44127836SJohn.Forte@Sun.COM 	int fd;
44137836SJohn.Forte@Sun.COM 	int ioctlRet;
44147836SJohn.Forte@Sun.COM 	int cmd = STMF_IOCTL_LU_LIST;
44159585STim.Szeto@Sun.COM 	int i;
44167836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
44177836SJohn.Forte@Sun.COM 	slist_lu_t *fLuList;
44187836SJohn.Forte@Sun.COM 	uint32_t fLuListSize;
44199585STim.Szeto@Sun.COM 	uint32_t listCnt;
44207836SJohn.Forte@Sun.COM 
44217836SJohn.Forte@Sun.COM 	if (luList == NULL) {
44227836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
44237836SJohn.Forte@Sun.COM 	}
44247836SJohn.Forte@Sun.COM 
44257836SJohn.Forte@Sun.COM 	/* call init */
44267836SJohn.Forte@Sun.COM 	ret = initializeConfig();
44277836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
44287836SJohn.Forte@Sun.COM 		return (ret);
44297836SJohn.Forte@Sun.COM 	}
44307836SJohn.Forte@Sun.COM 
44317836SJohn.Forte@Sun.COM 	/*
44327836SJohn.Forte@Sun.COM 	 * Open control node for stmf
44337836SJohn.Forte@Sun.COM 	 */
44347836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
44357836SJohn.Forte@Sun.COM 		return (ret);
44367836SJohn.Forte@Sun.COM 
44377836SJohn.Forte@Sun.COM 	/*
44387836SJohn.Forte@Sun.COM 	 * Allocate ioctl input buffer
44397836SJohn.Forte@Sun.COM 	 */
44409585STim.Szeto@Sun.COM 	fLuListSize = ALLOC_LU;
44417836SJohn.Forte@Sun.COM 	fLuListSize = fLuListSize * (sizeof (slist_lu_t));
44427836SJohn.Forte@Sun.COM 	fLuList = (slist_lu_t *)calloc(1, fLuListSize);
44437836SJohn.Forte@Sun.COM 	if (fLuList == NULL) {
44449585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
44459585STim.Szeto@Sun.COM 		goto done;
44467836SJohn.Forte@Sun.COM 	}
44477836SJohn.Forte@Sun.COM 
44487836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
44497836SJohn.Forte@Sun.COM 	/*
44507836SJohn.Forte@Sun.COM 	 * Issue ioctl to get the LU list
44517836SJohn.Forte@Sun.COM 	 */
44527836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
44537836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = fLuListSize;
44547836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fLuList;
44557836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
44567836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
44577836SJohn.Forte@Sun.COM 		switch (errno) {
44587836SJohn.Forte@Sun.COM 			case EBUSY:
44597836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
44607836SJohn.Forte@Sun.COM 				break;
44619585STim.Szeto@Sun.COM 			case EPERM:
44627836SJohn.Forte@Sun.COM 			case EACCES:
44637836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
44647836SJohn.Forte@Sun.COM 				break;
44657836SJohn.Forte@Sun.COM 			default:
44667836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
44677836SJohn.Forte@Sun.COM 				    "stmfGetLogicalUnitList:ioctl errno(%d)",
44687836SJohn.Forte@Sun.COM 				    errno);
44697836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
44707836SJohn.Forte@Sun.COM 				break;
44717836SJohn.Forte@Sun.COM 		}
44727836SJohn.Forte@Sun.COM 		goto done;
44737836SJohn.Forte@Sun.COM 	}
44747836SJohn.Forte@Sun.COM 	/*
44757836SJohn.Forte@Sun.COM 	 * Check whether input buffer was large enough
44767836SJohn.Forte@Sun.COM 	 */
44779585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_LU) {
44787836SJohn.Forte@Sun.COM 		fLuListSize = stmfIoctl.stmf_obuf_max_nentries *
44797836SJohn.Forte@Sun.COM 		    sizeof (slist_lu_t);
44809585STim.Szeto@Sun.COM 		free(fLuList);
44819585STim.Szeto@Sun.COM 		fLuList = (slist_lu_t *)calloc(1, fLuListSize);
44827836SJohn.Forte@Sun.COM 		if (fLuList == NULL) {
44839585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NOMEM;
44849585STim.Szeto@Sun.COM 			goto done;
44857836SJohn.Forte@Sun.COM 		}
44867836SJohn.Forte@Sun.COM 		stmfIoctl.stmf_obuf_size = fLuListSize;
44877836SJohn.Forte@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fLuList;
44887836SJohn.Forte@Sun.COM 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
44897836SJohn.Forte@Sun.COM 		if (ioctlRet != 0) {
44907836SJohn.Forte@Sun.COM 			switch (errno) {
44917836SJohn.Forte@Sun.COM 				case EBUSY:
44927836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_BUSY;
44937836SJohn.Forte@Sun.COM 					break;
44949585STim.Szeto@Sun.COM 				case EPERM:
44957836SJohn.Forte@Sun.COM 				case EACCES:
44967836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_PERM;
44977836SJohn.Forte@Sun.COM 					break;
44987836SJohn.Forte@Sun.COM 				default:
44997836SJohn.Forte@Sun.COM 					syslog(LOG_DEBUG,
45007836SJohn.Forte@Sun.COM 					    "stmfGetLogicalUnitList:"
45017836SJohn.Forte@Sun.COM 					    "ioctl errno(%d)", errno);
45027836SJohn.Forte@Sun.COM 					ret = STMF_STATUS_ERROR;
45037836SJohn.Forte@Sun.COM 					break;
45047836SJohn.Forte@Sun.COM 			}
45057836SJohn.Forte@Sun.COM 			goto done;
45067836SJohn.Forte@Sun.COM 		}
45077836SJohn.Forte@Sun.COM 	}
45087836SJohn.Forte@Sun.COM 
45097836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
45107836SJohn.Forte@Sun.COM 		goto done;
45117836SJohn.Forte@Sun.COM 	}
45127836SJohn.Forte@Sun.COM 
45139585STim.Szeto@Sun.COM 	listCnt = stmfIoctl.stmf_obuf_nentries;
45147836SJohn.Forte@Sun.COM 
45157836SJohn.Forte@Sun.COM 	/*
45167836SJohn.Forte@Sun.COM 	 * allocate caller's buffer with the final size
45177836SJohn.Forte@Sun.COM 	 */
45187836SJohn.Forte@Sun.COM 	*luList = (stmfGuidList *)calloc(1, sizeof (stmfGuidList) +
45199585STim.Szeto@Sun.COM 	    listCnt * sizeof (stmfGuid));
45207836SJohn.Forte@Sun.COM 	if (*luList == NULL) {
45217836SJohn.Forte@Sun.COM 		ret = STMF_ERROR_NOMEM;
45227836SJohn.Forte@Sun.COM 		goto done;
45237836SJohn.Forte@Sun.COM 	}
45247836SJohn.Forte@Sun.COM 
45259585STim.Szeto@Sun.COM 	(*luList)->cnt = listCnt;
45269585STim.Szeto@Sun.COM 
45279585STim.Szeto@Sun.COM 	/* copy to caller's buffer */
45289585STim.Szeto@Sun.COM 	for (i = 0; i < listCnt; i++) {
45299585STim.Szeto@Sun.COM 		bcopy(&fLuList[i].lu_guid, (*luList)->guid[i].guid,
45309585STim.Szeto@Sun.COM 		    sizeof (stmfGuid));
45319585STim.Szeto@Sun.COM 	}
45329585STim.Szeto@Sun.COM 
45337836SJohn.Forte@Sun.COM 	/*
45349585STim.Szeto@Sun.COM 	 * sort the list. This gives a consistent view across gets
45357836SJohn.Forte@Sun.COM 	 */
45369585STim.Szeto@Sun.COM 	qsort((void *)&((*luList)->guid[0]), (*luList)->cnt,
45379585STim.Szeto@Sun.COM 	    sizeof (stmfGuid), guidCompare);
45387836SJohn.Forte@Sun.COM 
45397836SJohn.Forte@Sun.COM done:
45407836SJohn.Forte@Sun.COM 	(void) close(fd);
45417836SJohn.Forte@Sun.COM 	/*
45427836SJohn.Forte@Sun.COM 	 * free internal buffers
45437836SJohn.Forte@Sun.COM 	 */
45447836SJohn.Forte@Sun.COM 	free(fLuList);
45457836SJohn.Forte@Sun.COM 	return (ret);
45467836SJohn.Forte@Sun.COM }
45477836SJohn.Forte@Sun.COM 
45487836SJohn.Forte@Sun.COM /*
45497836SJohn.Forte@Sun.COM  * stmfGetLogicalUnitProperties
45507836SJohn.Forte@Sun.COM  *
45517836SJohn.Forte@Sun.COM  * Purpose:  Retrieves the properties for a logical unit
45527836SJohn.Forte@Sun.COM  *
45537836SJohn.Forte@Sun.COM  * lu - guid of the logical unit for which to retrieve properties
45547836SJohn.Forte@Sun.COM  * stmfLuProps - pointer to an stmfLogicalUnitProperties structure. On success,
45557836SJohn.Forte@Sun.COM  *               it contains the logical unit properties for the specified guid.
45567836SJohn.Forte@Sun.COM  */
45577836SJohn.Forte@Sun.COM int
45587836SJohn.Forte@Sun.COM stmfGetLogicalUnitProperties(stmfGuid *lu, stmfLogicalUnitProperties *luProps)
45597836SJohn.Forte@Sun.COM {
45607836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
45617836SJohn.Forte@Sun.COM 	int stmfRet;
45627836SJohn.Forte@Sun.COM 	int fd;
45637836SJohn.Forte@Sun.COM 	int ioctlRet;
45647836SJohn.Forte@Sun.COM 	int cmd = STMF_IOCTL_GET_LU_PROPERTIES;
45657836SJohn.Forte@Sun.COM 	stmfViewEntryList *viewEntryList = NULL;
45667836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
45677836SJohn.Forte@Sun.COM 	sioc_lu_props_t fLuProps;
45687836SJohn.Forte@Sun.COM 
45699585STim.Szeto@Sun.COM 	if (lu == NULL || luProps == NULL) {
45709585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
45717836SJohn.Forte@Sun.COM 	}
45727836SJohn.Forte@Sun.COM 
45737836SJohn.Forte@Sun.COM 	bzero(luProps, sizeof (stmfLogicalUnitProperties));
45747836SJohn.Forte@Sun.COM 
45757836SJohn.Forte@Sun.COM 	/* call init */
45767836SJohn.Forte@Sun.COM 	ret = initializeConfig();
45777836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
45787836SJohn.Forte@Sun.COM 		return (ret);
45797836SJohn.Forte@Sun.COM 	}
45807836SJohn.Forte@Sun.COM 
45817836SJohn.Forte@Sun.COM 	/*
45827836SJohn.Forte@Sun.COM 	 * Open control node for stmf
45837836SJohn.Forte@Sun.COM 	 */
45847836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
45857836SJohn.Forte@Sun.COM 		return (ret);
45867836SJohn.Forte@Sun.COM 
45877836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
45887836SJohn.Forte@Sun.COM 	/*
45897836SJohn.Forte@Sun.COM 	 * Issue ioctl to add to the host group
45907836SJohn.Forte@Sun.COM 	 */
45917836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
45927836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (stmfGuid);
45937836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)lu;
45947836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&fLuProps;
45957836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = sizeof (fLuProps);
45967836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
45977836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
45987836SJohn.Forte@Sun.COM 		switch (errno) {
45997836SJohn.Forte@Sun.COM 			case EBUSY:
46007836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
46017836SJohn.Forte@Sun.COM 				break;
46029585STim.Szeto@Sun.COM 			case EPERM:
46037836SJohn.Forte@Sun.COM 			case EACCES:
46047836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
46057836SJohn.Forte@Sun.COM 				break;
46067836SJohn.Forte@Sun.COM 			case ENOENT:
46077836SJohn.Forte@Sun.COM 				stmfRet = stmfGetViewEntryList(lu,
46087836SJohn.Forte@Sun.COM 				    &viewEntryList);
46097836SJohn.Forte@Sun.COM 				if (stmfRet == STMF_STATUS_SUCCESS) {
46107836SJohn.Forte@Sun.COM 					luProps->status =
46117836SJohn.Forte@Sun.COM 					    STMF_LOGICAL_UNIT_UNREGISTERED;
46127836SJohn.Forte@Sun.COM 					if (viewEntryList->cnt > 0) {
46137836SJohn.Forte@Sun.COM 						ret = STMF_STATUS_SUCCESS;
46147836SJohn.Forte@Sun.COM 					} else {
46157836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_NOT_FOUND;
46167836SJohn.Forte@Sun.COM 					}
46177836SJohn.Forte@Sun.COM 				} else {
46187836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_NOT_FOUND;
46197836SJohn.Forte@Sun.COM 				}
46207836SJohn.Forte@Sun.COM 				stmfFreeMemory(viewEntryList);
46217836SJohn.Forte@Sun.COM 				break;
46227836SJohn.Forte@Sun.COM 			default:
46237836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
46247836SJohn.Forte@Sun.COM 				    "stmfGetLogicalUnit:ioctl errno(%d)",
46257836SJohn.Forte@Sun.COM 				    errno);
46267836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
46277836SJohn.Forte@Sun.COM 				break;
46287836SJohn.Forte@Sun.COM 		}
46297836SJohn.Forte@Sun.COM 		goto done;
46307836SJohn.Forte@Sun.COM 	}
46317836SJohn.Forte@Sun.COM 
46327836SJohn.Forte@Sun.COM 	bcopy(fLuProps.lu_provider_name, luProps->providerName,
46337836SJohn.Forte@Sun.COM 	    sizeof (fLuProps.lu_provider_name));
46347836SJohn.Forte@Sun.COM 	if (fLuProps.lu_state == STMF_STATE_ONLINE) {
46357836SJohn.Forte@Sun.COM 		luProps->status = STMF_LOGICAL_UNIT_ONLINE;
46367836SJohn.Forte@Sun.COM 	} else if (fLuProps.lu_state == STMF_STATE_OFFLINE) {
46377836SJohn.Forte@Sun.COM 		luProps->status = STMF_LOGICAL_UNIT_OFFLINE;
46387836SJohn.Forte@Sun.COM 	} else if (fLuProps.lu_state == STMF_STATE_ONLINING) {
46397836SJohn.Forte@Sun.COM 		luProps->status = STMF_LOGICAL_UNIT_ONLINING;
46407836SJohn.Forte@Sun.COM 	} else if (fLuProps.lu_state == STMF_STATE_OFFLINING) {
46417836SJohn.Forte@Sun.COM 		luProps->status = STMF_LOGICAL_UNIT_OFFLINING;
46427836SJohn.Forte@Sun.COM 	}
46437836SJohn.Forte@Sun.COM 	bcopy(fLuProps.lu_alias, luProps->alias, sizeof (luProps->alias));
46447836SJohn.Forte@Sun.COM done:
46457836SJohn.Forte@Sun.COM 	(void) close(fd);
46467836SJohn.Forte@Sun.COM 	return (ret);
46477836SJohn.Forte@Sun.COM }
46487836SJohn.Forte@Sun.COM 
46497836SJohn.Forte@Sun.COM /*
46507836SJohn.Forte@Sun.COM  * stmfGetState
46517836SJohn.Forte@Sun.COM  *
46527836SJohn.Forte@Sun.COM  * Purpose: retrieve the current state of the stmf module
46537836SJohn.Forte@Sun.COM  *
46547836SJohn.Forte@Sun.COM  * state - pointer to stmfState structure allocated by the caller
46557836SJohn.Forte@Sun.COM  *         On success, contains the state of stmf
46567836SJohn.Forte@Sun.COM  */
46577836SJohn.Forte@Sun.COM int
46587836SJohn.Forte@Sun.COM stmfGetState(stmfState *state)
46597836SJohn.Forte@Sun.COM {
46607836SJohn.Forte@Sun.COM 	int ret;
46617836SJohn.Forte@Sun.COM 	stmf_state_desc_t iState;
46627836SJohn.Forte@Sun.COM 
46637836SJohn.Forte@Sun.COM 	if (state == NULL) {
46647836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
46657836SJohn.Forte@Sun.COM 	}
46667836SJohn.Forte@Sun.COM 
46677836SJohn.Forte@Sun.COM 	ret = getStmfState(&iState);
46687836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
46697836SJohn.Forte@Sun.COM 		return (ret);
46707836SJohn.Forte@Sun.COM 	}
46717836SJohn.Forte@Sun.COM 	switch (iState.state) {
46727836SJohn.Forte@Sun.COM 		case STMF_STATE_ONLINE:
46737836SJohn.Forte@Sun.COM 			state->operationalState =
46747836SJohn.Forte@Sun.COM 			    STMF_SERVICE_STATE_ONLINE;
46757836SJohn.Forte@Sun.COM 			break;
46767836SJohn.Forte@Sun.COM 		case STMF_STATE_OFFLINE:
46777836SJohn.Forte@Sun.COM 			state->operationalState =
46787836SJohn.Forte@Sun.COM 			    STMF_SERVICE_STATE_OFFLINE;
46797836SJohn.Forte@Sun.COM 			break;
46807836SJohn.Forte@Sun.COM 		case STMF_STATE_ONLINING:
46817836SJohn.Forte@Sun.COM 			state->operationalState =
46827836SJohn.Forte@Sun.COM 			    STMF_SERVICE_STATE_ONLINING;
46837836SJohn.Forte@Sun.COM 			break;
46847836SJohn.Forte@Sun.COM 		case STMF_STATE_OFFLINING:
46857836SJohn.Forte@Sun.COM 			state->operationalState =
46867836SJohn.Forte@Sun.COM 			    STMF_SERVICE_STATE_OFFLINING;
46877836SJohn.Forte@Sun.COM 			break;
46887836SJohn.Forte@Sun.COM 		default:
46897836SJohn.Forte@Sun.COM 			state->operationalState =
46907836SJohn.Forte@Sun.COM 			    STMF_SERVICE_STATE_UNKNOWN;
46917836SJohn.Forte@Sun.COM 			break;
46927836SJohn.Forte@Sun.COM 	}
46937836SJohn.Forte@Sun.COM 	switch (iState.config_state) {
46947836SJohn.Forte@Sun.COM 		case STMF_CONFIG_NONE:
46957836SJohn.Forte@Sun.COM 			state->configState = STMF_CONFIG_STATE_NONE;
46967836SJohn.Forte@Sun.COM 			break;
46977836SJohn.Forte@Sun.COM 		case STMF_CONFIG_INIT:
46987836SJohn.Forte@Sun.COM 			state->configState = STMF_CONFIG_STATE_INIT;
46997836SJohn.Forte@Sun.COM 			break;
47007836SJohn.Forte@Sun.COM 		case STMF_CONFIG_INIT_DONE:
47017836SJohn.Forte@Sun.COM 			state->configState =
47027836SJohn.Forte@Sun.COM 			    STMF_CONFIG_STATE_INIT_DONE;
47037836SJohn.Forte@Sun.COM 			break;
47047836SJohn.Forte@Sun.COM 		default:
47057836SJohn.Forte@Sun.COM 			state->configState =
47067836SJohn.Forte@Sun.COM 			    STMF_CONFIG_STATE_UNKNOWN;
47077836SJohn.Forte@Sun.COM 			break;
47087836SJohn.Forte@Sun.COM 	}
47097836SJohn.Forte@Sun.COM 	return (STMF_STATUS_SUCCESS);
47107836SJohn.Forte@Sun.COM }
47117836SJohn.Forte@Sun.COM 
47127836SJohn.Forte@Sun.COM /*
47137836SJohn.Forte@Sun.COM  * stmfGetViewEntryList
47147836SJohn.Forte@Sun.COM  *
47157836SJohn.Forte@Sun.COM  * Purpose: Retrieves the list of view entries for the specified
47167836SJohn.Forte@Sun.COM  *          logical unit.
47177836SJohn.Forte@Sun.COM  *
47187836SJohn.Forte@Sun.COM  * lu - the guid of the logical unit for which to retrieve the view entry list
47197836SJohn.Forte@Sun.COM  * viewEntryList - a pointer to a pointer to a stmfViewEntryList structure. On
47207836SJohn.Forte@Sun.COM  *                 success, contains the list of view entries.
47217836SJohn.Forte@Sun.COM  */
47227836SJohn.Forte@Sun.COM int
47237836SJohn.Forte@Sun.COM stmfGetViewEntryList(stmfGuid *lu, stmfViewEntryList **viewEntryList)
47247836SJohn.Forte@Sun.COM {
47257836SJohn.Forte@Sun.COM 	int ret;
47269585STim.Szeto@Sun.COM 	int fd;
47279585STim.Szeto@Sun.COM 	int ioctlRet;
47289585STim.Szeto@Sun.COM 	int cmd = STMF_IOCTL_LU_VE_LIST;
47299585STim.Szeto@Sun.COM 	int i;
47309585STim.Szeto@Sun.COM 	stmf_iocdata_t stmfIoctl;
47319585STim.Szeto@Sun.COM 	stmf_view_op_entry_t *fVeList;
47329585STim.Szeto@Sun.COM 	uint32_t fVeListSize;
47339585STim.Szeto@Sun.COM 	uint32_t listCnt;
47347836SJohn.Forte@Sun.COM 
47357836SJohn.Forte@Sun.COM 	if (lu == NULL || viewEntryList == NULL) {
47367836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
47377836SJohn.Forte@Sun.COM 	}
47387836SJohn.Forte@Sun.COM 
47399585STim.Szeto@Sun.COM 	/* call init */
47409585STim.Szeto@Sun.COM 	ret = initializeConfig();
47419585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
47429585STim.Szeto@Sun.COM 		return (ret);
47439585STim.Szeto@Sun.COM 	}
47449585STim.Szeto@Sun.COM 
47459585STim.Szeto@Sun.COM 	/*
47469585STim.Szeto@Sun.COM 	 * Open control node for stmf
47479585STim.Szeto@Sun.COM 	 */
47489585STim.Szeto@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
47499585STim.Szeto@Sun.COM 		return (ret);
47509585STim.Szeto@Sun.COM 
47519585STim.Szeto@Sun.COM 	/*
47529585STim.Szeto@Sun.COM 	 * Allocate ioctl input buffer
47539585STim.Szeto@Sun.COM 	 */
47549585STim.Szeto@Sun.COM 	fVeListSize = ALLOC_VE;
47559585STim.Szeto@Sun.COM 	fVeListSize = fVeListSize * (sizeof (stmf_view_op_entry_t));
47569585STim.Szeto@Sun.COM 	fVeList = (stmf_view_op_entry_t *)calloc(1, fVeListSize);
47579585STim.Szeto@Sun.COM 	if (fVeList == NULL) {
47589585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
47599585STim.Szeto@Sun.COM 		goto done;
47609585STim.Szeto@Sun.COM 	}
47619585STim.Szeto@Sun.COM 
47629585STim.Szeto@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
47639585STim.Szeto@Sun.COM 	/*
47649585STim.Szeto@Sun.COM 	 * Issue ioctl to get the LU list
47659585STim.Szeto@Sun.COM 	 */
47669585STim.Szeto@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
47679585STim.Szeto@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)lu;
47689585STim.Szeto@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (stmfGuid);
47699585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf_size = fVeListSize;
47709585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fVeList;
47719585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
47729585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
47739585STim.Szeto@Sun.COM 		switch (errno) {
47749585STim.Szeto@Sun.COM 			case EBUSY:
47759585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
47769585STim.Szeto@Sun.COM 				break;
47779585STim.Szeto@Sun.COM 			case EPERM:
47789585STim.Szeto@Sun.COM 			case EACCES:
47799585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
47809585STim.Szeto@Sun.COM 				break;
47819585STim.Szeto@Sun.COM 			default:
47829585STim.Szeto@Sun.COM 				syslog(LOG_DEBUG,
47839585STim.Szeto@Sun.COM 				    "stmfGetViewEntryList:ioctl errno(%d)",
47849585STim.Szeto@Sun.COM 				    errno);
47859585STim.Szeto@Sun.COM 				ret = STMF_STATUS_ERROR;
47869585STim.Szeto@Sun.COM 				break;
47879585STim.Szeto@Sun.COM 		}
47889585STim.Szeto@Sun.COM 		goto done;
47899585STim.Szeto@Sun.COM 	}
47909585STim.Szeto@Sun.COM 	/*
47919585STim.Szeto@Sun.COM 	 * Check whether input buffer was large enough
47929585STim.Szeto@Sun.COM 	 */
47939585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_VE) {
47949585STim.Szeto@Sun.COM 		bzero(&stmfIoctl, sizeof (stmfIoctl));
47959585STim.Szeto@Sun.COM 		fVeListSize = stmfIoctl.stmf_obuf_max_nentries *
47969585STim.Szeto@Sun.COM 		    sizeof (stmf_view_op_entry_t);
47979585STim.Szeto@Sun.COM 		free(fVeList);
47989585STim.Szeto@Sun.COM 		fVeList = (stmf_view_op_entry_t *)calloc(1, fVeListSize);
47999585STim.Szeto@Sun.COM 		if (fVeList == NULL) {
48009585STim.Szeto@Sun.COM 			return (STMF_ERROR_NOMEM);
48019585STim.Szeto@Sun.COM 		}
48029585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf_size = fVeListSize;
48039585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fVeList;
48049585STim.Szeto@Sun.COM 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
48059585STim.Szeto@Sun.COM 		if (ioctlRet != 0) {
48069585STim.Szeto@Sun.COM 			switch (errno) {
48079585STim.Szeto@Sun.COM 				case EBUSY:
48089585STim.Szeto@Sun.COM 					ret = STMF_ERROR_BUSY;
48099585STim.Szeto@Sun.COM 					break;
48109585STim.Szeto@Sun.COM 				case EPERM:
48119585STim.Szeto@Sun.COM 				case EACCES:
48129585STim.Szeto@Sun.COM 					ret = STMF_ERROR_PERM;
48139585STim.Szeto@Sun.COM 					break;
48149585STim.Szeto@Sun.COM 				default:
48159585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
48169585STim.Szeto@Sun.COM 					    "stmfGetLogicalUnitList:"
48179585STim.Szeto@Sun.COM 					    "ioctl errno(%d)", errno);
48189585STim.Szeto@Sun.COM 					ret = STMF_STATUS_ERROR;
48199585STim.Szeto@Sun.COM 					break;
48209585STim.Szeto@Sun.COM 			}
48219585STim.Szeto@Sun.COM 			goto done;
48229585STim.Szeto@Sun.COM 		}
48239585STim.Szeto@Sun.COM 	}
48249585STim.Szeto@Sun.COM 
48259585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
48269585STim.Szeto@Sun.COM 		goto done;
48279585STim.Szeto@Sun.COM 	}
48289585STim.Szeto@Sun.COM 
48299585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_nentries == 0) {
48309585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOT_FOUND;
48319585STim.Szeto@Sun.COM 		goto done;
48329585STim.Szeto@Sun.COM 	}
48339585STim.Szeto@Sun.COM 
48349585STim.Szeto@Sun.COM 	listCnt = stmfIoctl.stmf_obuf_nentries;
48359585STim.Szeto@Sun.COM 
48369585STim.Szeto@Sun.COM 	/*
48379585STim.Szeto@Sun.COM 	 * allocate caller's buffer with the final size
48389585STim.Szeto@Sun.COM 	 */
48399585STim.Szeto@Sun.COM 	*viewEntryList = (stmfViewEntryList *)calloc(1,
48409585STim.Szeto@Sun.COM 	    sizeof (stmfViewEntryList) + listCnt * sizeof (stmfViewEntry));
48419585STim.Szeto@Sun.COM 	if (*viewEntryList == NULL) {
48429585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
48439585STim.Szeto@Sun.COM 		goto done;
48449585STim.Szeto@Sun.COM 	}
48459585STim.Szeto@Sun.COM 
48469585STim.Szeto@Sun.COM 	(*viewEntryList)->cnt = listCnt;
48479585STim.Szeto@Sun.COM 
48489585STim.Szeto@Sun.COM 	/* copy to caller's buffer */
48499585STim.Szeto@Sun.COM 	for (i = 0; i < listCnt; i++) {
48509585STim.Szeto@Sun.COM 		(*viewEntryList)->ve[i].veIndexValid = B_TRUE;
48519585STim.Szeto@Sun.COM 		(*viewEntryList)->ve[i].veIndex = fVeList[i].ve_ndx;
48529585STim.Szeto@Sun.COM 		if (fVeList[i].ve_all_hosts == 1) {
48539585STim.Szeto@Sun.COM 			(*viewEntryList)->ve[i].allHosts = B_TRUE;
48549585STim.Szeto@Sun.COM 		} else {
48559585STim.Szeto@Sun.COM 			bcopy(fVeList[i].ve_host_group.name,
48569585STim.Szeto@Sun.COM 			    (*viewEntryList)->ve[i].hostGroup,
48579585STim.Szeto@Sun.COM 			    fVeList[i].ve_host_group.name_size);
48589585STim.Szeto@Sun.COM 		}
48599585STim.Szeto@Sun.COM 		if (fVeList[i].ve_all_targets == 1) {
48609585STim.Szeto@Sun.COM 			(*viewEntryList)->ve[i].allTargets = B_TRUE;
48619585STim.Szeto@Sun.COM 		} else {
48629585STim.Szeto@Sun.COM 			bcopy(fVeList[i].ve_target_group.name,
48639585STim.Szeto@Sun.COM 			    (*viewEntryList)->ve[i].targetGroup,
48649585STim.Szeto@Sun.COM 			    fVeList[i].ve_target_group.name_size);
48659585STim.Szeto@Sun.COM 		}
48669585STim.Szeto@Sun.COM 		bcopy(fVeList[i].ve_lu_nbr, (*viewEntryList)->ve[i].luNbr,
48679585STim.Szeto@Sun.COM 		    sizeof ((*viewEntryList)->ve[i].luNbr));
48689585STim.Szeto@Sun.COM 		(*viewEntryList)->ve[i].luNbrValid = B_TRUE;
48699585STim.Szeto@Sun.COM 	}
48709585STim.Szeto@Sun.COM 
48719585STim.Szeto@Sun.COM 	/*
48729585STim.Szeto@Sun.COM 	 * sort the list. This gives a consistent view across gets
48739585STim.Szeto@Sun.COM 	 */
48749585STim.Szeto@Sun.COM 	qsort((void *)&((*viewEntryList)->ve[0]), (*viewEntryList)->cnt,
48759585STim.Szeto@Sun.COM 	    sizeof (stmfViewEntry), viewEntryCompare);
48769585STim.Szeto@Sun.COM 
48779585STim.Szeto@Sun.COM done:
48789585STim.Szeto@Sun.COM 	(void) close(fd);
48799585STim.Szeto@Sun.COM 	/*
48809585STim.Szeto@Sun.COM 	 * free internal buffers
48819585STim.Szeto@Sun.COM 	 */
48829585STim.Szeto@Sun.COM 	free(fVeList);
48837836SJohn.Forte@Sun.COM 	return (ret);
48847836SJohn.Forte@Sun.COM }
48857836SJohn.Forte@Sun.COM 
48869585STim.Szeto@Sun.COM 
48877836SJohn.Forte@Sun.COM /*
48887836SJohn.Forte@Sun.COM  * loadHostGroups
48897836SJohn.Forte@Sun.COM  *
48907836SJohn.Forte@Sun.COM  * Purpose - issues the ioctl to load the host groups into stmf
48917836SJohn.Forte@Sun.COM  *
48927836SJohn.Forte@Sun.COM  * fd - file descriptor for the control node of stmf.
48937836SJohn.Forte@Sun.COM  * groupList - populated host group list
48947836SJohn.Forte@Sun.COM  */
48957836SJohn.Forte@Sun.COM static int
48967836SJohn.Forte@Sun.COM loadHostGroups(int fd, stmfGroupList *groupList)
48977836SJohn.Forte@Sun.COM {
48987836SJohn.Forte@Sun.COM 	int i, j;
48997836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
49007836SJohn.Forte@Sun.COM 	stmfGroupProperties *groupProps = NULL;
49017836SJohn.Forte@Sun.COM 
49027836SJohn.Forte@Sun.COM 	for (i = 0; i < groupList->cnt; i++) {
49037836SJohn.Forte@Sun.COM 		if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_HOST_GROUP,
49047836SJohn.Forte@Sun.COM 		    &(groupList->name[i]))) != STMF_STATUS_SUCCESS) {
49057836SJohn.Forte@Sun.COM 			goto out;
49067836SJohn.Forte@Sun.COM 		}
49079585STim.Szeto@Sun.COM 		ret = iLoadGroupMembersFromPs(&(groupList->name[i]),
49089585STim.Szeto@Sun.COM 		    &groupProps, HOST_GROUP);
49097836SJohn.Forte@Sun.COM 		for (j = 0; j < groupProps->cnt; j++) {
49107836SJohn.Forte@Sun.COM 			if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_HG_ENTRY,
49117836SJohn.Forte@Sun.COM 			    &(groupList->name[i]), &(groupProps->name[j])))
49127836SJohn.Forte@Sun.COM 			    != STMF_STATUS_SUCCESS) {
49137836SJohn.Forte@Sun.COM 				goto out;
49147836SJohn.Forte@Sun.COM 			}
49157836SJohn.Forte@Sun.COM 		}
49167836SJohn.Forte@Sun.COM 	}
49177836SJohn.Forte@Sun.COM 
49187836SJohn.Forte@Sun.COM 
49197836SJohn.Forte@Sun.COM out:
49207836SJohn.Forte@Sun.COM 	stmfFreeMemory(groupProps);
49217836SJohn.Forte@Sun.COM 	return (ret);
49227836SJohn.Forte@Sun.COM }
49237836SJohn.Forte@Sun.COM 
49247836SJohn.Forte@Sun.COM /*
49257836SJohn.Forte@Sun.COM  * loadTargetGroups
49267836SJohn.Forte@Sun.COM  *
49277836SJohn.Forte@Sun.COM  * Purpose - issues the ioctl to load the target groups into stmf
49287836SJohn.Forte@Sun.COM  *
49297836SJohn.Forte@Sun.COM  * fd - file descriptor for the control node of stmf.
49307836SJohn.Forte@Sun.COM  * groupList - populated target group list.
49317836SJohn.Forte@Sun.COM  */
49327836SJohn.Forte@Sun.COM static int
49337836SJohn.Forte@Sun.COM loadTargetGroups(int fd, stmfGroupList *groupList)
49347836SJohn.Forte@Sun.COM {
49357836SJohn.Forte@Sun.COM 	int i, j;
49367836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
49377836SJohn.Forte@Sun.COM 	stmfGroupProperties *groupProps = NULL;
49387836SJohn.Forte@Sun.COM 
49397836SJohn.Forte@Sun.COM 	for (i = 0; i < groupList->cnt; i++) {
49407836SJohn.Forte@Sun.COM 		if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_TARGET_GROUP,
49417836SJohn.Forte@Sun.COM 		    &(groupList->name[i]))) != STMF_STATUS_SUCCESS) {
49427836SJohn.Forte@Sun.COM 			goto out;
49437836SJohn.Forte@Sun.COM 		}
49449585STim.Szeto@Sun.COM 		ret = iLoadGroupMembersFromPs(&(groupList->name[i]),
49459585STim.Szeto@Sun.COM 		    &groupProps, TARGET_GROUP);
49467836SJohn.Forte@Sun.COM 		for (j = 0; j < groupProps->cnt; j++) {
49477836SJohn.Forte@Sun.COM 			if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_TG_ENTRY,
49487836SJohn.Forte@Sun.COM 			    &(groupList->name[i]), &(groupProps->name[j])))
49497836SJohn.Forte@Sun.COM 			    != STMF_STATUS_SUCCESS) {
49507836SJohn.Forte@Sun.COM 				goto out;
49517836SJohn.Forte@Sun.COM 			}
49527836SJohn.Forte@Sun.COM 		}
49537836SJohn.Forte@Sun.COM 	}
49547836SJohn.Forte@Sun.COM 
49557836SJohn.Forte@Sun.COM 
49567836SJohn.Forte@Sun.COM out:
49577836SJohn.Forte@Sun.COM 	stmfFreeMemory(groupProps);
49587836SJohn.Forte@Sun.COM 	return (ret);
49597836SJohn.Forte@Sun.COM }
49607836SJohn.Forte@Sun.COM 
49617836SJohn.Forte@Sun.COM 
49627836SJohn.Forte@Sun.COM /*
49637836SJohn.Forte@Sun.COM  * loadStore
49647836SJohn.Forte@Sun.COM  *
49657836SJohn.Forte@Sun.COM  * Purpose: Load the configuration data from the store
49667836SJohn.Forte@Sun.COM  *
49677836SJohn.Forte@Sun.COM  * First load the host groups and target groups, then the view entries
49687836SJohn.Forte@Sun.COM  * and finally the provider data
49697836SJohn.Forte@Sun.COM  *
49707836SJohn.Forte@Sun.COM  * fd - file descriptor of control node for stmf.
49717836SJohn.Forte@Sun.COM  */
49727836SJohn.Forte@Sun.COM static int
49737836SJohn.Forte@Sun.COM loadStore(int fd)
49747836SJohn.Forte@Sun.COM {
49757836SJohn.Forte@Sun.COM 	int ret;
49767836SJohn.Forte@Sun.COM 	int i, j;
49777836SJohn.Forte@Sun.COM 	stmfGroupList *groupList = NULL;
49787836SJohn.Forte@Sun.COM 	stmfGuidList *guidList = NULL;
49797836SJohn.Forte@Sun.COM 	stmfViewEntryList *viewEntryList = NULL;
49807836SJohn.Forte@Sun.COM 	stmfProviderList *providerList = NULL;
49817836SJohn.Forte@Sun.COM 	int providerType;
49827836SJohn.Forte@Sun.COM 	nvlist_t *nvl = NULL;
49837836SJohn.Forte@Sun.COM 
49847836SJohn.Forte@Sun.COM 
49857836SJohn.Forte@Sun.COM 
49867836SJohn.Forte@Sun.COM 	/* load host groups */
49879585STim.Szeto@Sun.COM 	ret = iLoadGroupFromPs(&groupList, HOST_GROUP);
49887836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
49897836SJohn.Forte@Sun.COM 		return (ret);
49907836SJohn.Forte@Sun.COM 	}
49917836SJohn.Forte@Sun.COM 	ret = loadHostGroups(fd, groupList);
49927836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
49937836SJohn.Forte@Sun.COM 		goto out;
49947836SJohn.Forte@Sun.COM 	}
49957836SJohn.Forte@Sun.COM 
49967836SJohn.Forte@Sun.COM 	stmfFreeMemory(groupList);
49977836SJohn.Forte@Sun.COM 	groupList = NULL;
49987836SJohn.Forte@Sun.COM 
49997836SJohn.Forte@Sun.COM 	/* load target groups */
50009585STim.Szeto@Sun.COM 	ret = iLoadGroupFromPs(&groupList, TARGET_GROUP);
50017836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
50027836SJohn.Forte@Sun.COM 		goto out;
50037836SJohn.Forte@Sun.COM 	}
50047836SJohn.Forte@Sun.COM 	ret = loadTargetGroups(fd, groupList);
50057836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
50067836SJohn.Forte@Sun.COM 		goto out;
50077836SJohn.Forte@Sun.COM 	}
50087836SJohn.Forte@Sun.COM 
50097836SJohn.Forte@Sun.COM 	stmfFreeMemory(groupList);
50107836SJohn.Forte@Sun.COM 	groupList = NULL;
50117836SJohn.Forte@Sun.COM 
50127836SJohn.Forte@Sun.COM 	/* Get the guid list */
50137836SJohn.Forte@Sun.COM 	ret = psGetLogicalUnitList(&guidList);
50147836SJohn.Forte@Sun.COM 	switch (ret) {
50157836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
50167836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
50177836SJohn.Forte@Sun.COM 			break;
50187836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
50197836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
50207836SJohn.Forte@Sun.COM 			break;
50217836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
50227836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
50237836SJohn.Forte@Sun.COM 			break;
50247836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
50257836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
50267836SJohn.Forte@Sun.COM 			break;
50277836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
50287836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
50297836SJohn.Forte@Sun.COM 			break;
50307836SJohn.Forte@Sun.COM 		default:
50317836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
50327836SJohn.Forte@Sun.COM 			break;
50337836SJohn.Forte@Sun.COM 	}
50347836SJohn.Forte@Sun.COM 
50357836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
50367836SJohn.Forte@Sun.COM 		goto out;
50377836SJohn.Forte@Sun.COM 	}
50387836SJohn.Forte@Sun.COM 
50397836SJohn.Forte@Sun.COM 	/*
50407836SJohn.Forte@Sun.COM 	 * We have the guid list, now get the corresponding
50417836SJohn.Forte@Sun.COM 	 * view entries for each guid
50427836SJohn.Forte@Sun.COM 	 */
50437836SJohn.Forte@Sun.COM 	for (i = 0; i < guidList->cnt; i++) {
50447836SJohn.Forte@Sun.COM 		ret = psGetViewEntryList(&guidList->guid[i], &viewEntryList);
50457836SJohn.Forte@Sun.COM 		switch (ret) {
50467836SJohn.Forte@Sun.COM 			case STMF_PS_SUCCESS:
50477836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_SUCCESS;
50487836SJohn.Forte@Sun.COM 				break;
50497836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_NOT_FOUND:
50507836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
50517836SJohn.Forte@Sun.COM 				break;
50527836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_BUSY:
50537836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
50547836SJohn.Forte@Sun.COM 				break;
50557836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_SERVICE_NOT_FOUND:
50567836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_SERVICE_NOT_FOUND;
50577836SJohn.Forte@Sun.COM 				break;
50587836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_VERSION_MISMATCH:
50597836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_SERVICE_DATA_VERSION;
50607836SJohn.Forte@Sun.COM 				break;
50617836SJohn.Forte@Sun.COM 			default:
50627836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
50637836SJohn.Forte@Sun.COM 				break;
50647836SJohn.Forte@Sun.COM 		}
50657836SJohn.Forte@Sun.COM 		if (ret != STMF_STATUS_SUCCESS) {
50667836SJohn.Forte@Sun.COM 			goto out;
50677836SJohn.Forte@Sun.COM 		}
50687836SJohn.Forte@Sun.COM 		for (j = 0; j < viewEntryList->cnt; j++) {
50697836SJohn.Forte@Sun.COM 			ret = addViewEntryIoctl(fd, &guidList->guid[i],
50707836SJohn.Forte@Sun.COM 			    &viewEntryList->ve[j]);
50717836SJohn.Forte@Sun.COM 			if (ret != STMF_STATUS_SUCCESS) {
50727836SJohn.Forte@Sun.COM 				goto out;
50737836SJohn.Forte@Sun.COM 			}
50747836SJohn.Forte@Sun.COM 		}
50757836SJohn.Forte@Sun.COM 	}
50767836SJohn.Forte@Sun.COM 
50777836SJohn.Forte@Sun.COM 	/* get the list of providers that have data */
50787836SJohn.Forte@Sun.COM 	ret = psGetProviderDataList(&providerList);
50797836SJohn.Forte@Sun.COM 	switch (ret) {
50807836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
50817836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
50827836SJohn.Forte@Sun.COM 			break;
50837836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
50847836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
50857836SJohn.Forte@Sun.COM 			break;
50867836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
50877836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
50887836SJohn.Forte@Sun.COM 			break;
50897836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
50907836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
50917836SJohn.Forte@Sun.COM 			break;
50927836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
50937836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
50947836SJohn.Forte@Sun.COM 			break;
50957836SJohn.Forte@Sun.COM 		default:
50967836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
50977836SJohn.Forte@Sun.COM 			break;
50987836SJohn.Forte@Sun.COM 	}
50997836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
51007836SJohn.Forte@Sun.COM 		goto out;
51017836SJohn.Forte@Sun.COM 	}
51027836SJohn.Forte@Sun.COM 
51037836SJohn.Forte@Sun.COM 	for (i = 0; i < providerList->cnt; i++) {
51047836SJohn.Forte@Sun.COM 		providerType = providerList->provider[i].providerType;
51057836SJohn.Forte@Sun.COM 		ret = psGetProviderData(providerList->provider[i].name,
51067836SJohn.Forte@Sun.COM 		    &nvl, providerType, NULL);
51077836SJohn.Forte@Sun.COM 		switch (ret) {
51087836SJohn.Forte@Sun.COM 			case STMF_PS_SUCCESS:
51097836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_SUCCESS;
51107836SJohn.Forte@Sun.COM 				break;
51117836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_NOT_FOUND:
51127836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
51137836SJohn.Forte@Sun.COM 				break;
51147836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_BUSY:
51157836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
51167836SJohn.Forte@Sun.COM 				break;
51177836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_SERVICE_NOT_FOUND:
51187836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_SERVICE_NOT_FOUND;
51197836SJohn.Forte@Sun.COM 				break;
51207836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_VERSION_MISMATCH:
51217836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_SERVICE_DATA_VERSION;
51227836SJohn.Forte@Sun.COM 				break;
51237836SJohn.Forte@Sun.COM 			default:
51247836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
51257836SJohn.Forte@Sun.COM 				break;
51267836SJohn.Forte@Sun.COM 		}
51277836SJohn.Forte@Sun.COM 		if (ret != STMF_STATUS_SUCCESS) {
51287836SJohn.Forte@Sun.COM 			goto out;
51297836SJohn.Forte@Sun.COM 		}
51307836SJohn.Forte@Sun.COM 
51317836SJohn.Forte@Sun.COM 		/* call setProviderData */
51327836SJohn.Forte@Sun.COM 		ret = setProviderData(fd, providerList->provider[i].name, nvl,
51339585STim.Szeto@Sun.COM 		    providerType, NULL);
51347836SJohn.Forte@Sun.COM 		switch (ret) {
51357836SJohn.Forte@Sun.COM 			case STMF_PS_SUCCESS:
51367836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_SUCCESS;
51377836SJohn.Forte@Sun.COM 				break;
51387836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_NOT_FOUND:
51397836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
51407836SJohn.Forte@Sun.COM 				break;
51417836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_BUSY:
51427836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
51437836SJohn.Forte@Sun.COM 				break;
51447836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_SERVICE_NOT_FOUND:
51457836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_SERVICE_NOT_FOUND;
51467836SJohn.Forte@Sun.COM 				break;
51477836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_VERSION_MISMATCH:
51487836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_SERVICE_DATA_VERSION;
51497836SJohn.Forte@Sun.COM 				break;
51507836SJohn.Forte@Sun.COM 			default:
51517836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
51527836SJohn.Forte@Sun.COM 				break;
51537836SJohn.Forte@Sun.COM 		}
51547836SJohn.Forte@Sun.COM 		if (ret != STMF_STATUS_SUCCESS) {
51557836SJohn.Forte@Sun.COM 			goto out;
51567836SJohn.Forte@Sun.COM 		}
51577836SJohn.Forte@Sun.COM 
51587836SJohn.Forte@Sun.COM 		nvlist_free(nvl);
51597836SJohn.Forte@Sun.COM 		nvl = NULL;
51607836SJohn.Forte@Sun.COM 	}
51617836SJohn.Forte@Sun.COM out:
51627836SJohn.Forte@Sun.COM 	if (groupList != NULL) {
51637836SJohn.Forte@Sun.COM 		free(groupList);
51647836SJohn.Forte@Sun.COM 	}
51657836SJohn.Forte@Sun.COM 	if (guidList != NULL) {
51667836SJohn.Forte@Sun.COM 		free(guidList);
51677836SJohn.Forte@Sun.COM 	}
51687836SJohn.Forte@Sun.COM 	if (viewEntryList != NULL) {
51697836SJohn.Forte@Sun.COM 		free(viewEntryList);
51707836SJohn.Forte@Sun.COM 	}
51717836SJohn.Forte@Sun.COM 	if (nvl != NULL) {
51727836SJohn.Forte@Sun.COM 		nvlist_free(nvl);
51737836SJohn.Forte@Sun.COM 	}
51747836SJohn.Forte@Sun.COM 	return (ret);
51757836SJohn.Forte@Sun.COM }
51767836SJohn.Forte@Sun.COM 
51777836SJohn.Forte@Sun.COM /*
517810725SJohn.Forte@Sun.COM  * stmfGetAluaState
517910725SJohn.Forte@Sun.COM  *
518010725SJohn.Forte@Sun.COM  * Purpose - Get the alua state
518110725SJohn.Forte@Sun.COM  *
518210725SJohn.Forte@Sun.COM  */
518310725SJohn.Forte@Sun.COM int
518410725SJohn.Forte@Sun.COM stmfGetAluaState(boolean_t *enabled, uint32_t *node)
518510725SJohn.Forte@Sun.COM {
518610725SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
518710725SJohn.Forte@Sun.COM 	int fd;
518810725SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl = {0};
518910725SJohn.Forte@Sun.COM 	stmf_alua_state_desc_t alua_state = {0};
519010725SJohn.Forte@Sun.COM 	int ioctlRet;
519110725SJohn.Forte@Sun.COM 
519210725SJohn.Forte@Sun.COM 	if (enabled == NULL || node == NULL) {
519310725SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
519410725SJohn.Forte@Sun.COM 	}
519510725SJohn.Forte@Sun.COM 
519610725SJohn.Forte@Sun.COM 	/*
519710725SJohn.Forte@Sun.COM 	 * Open control node for stmf
519810725SJohn.Forte@Sun.COM 	 */
519910725SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
520010725SJohn.Forte@Sun.COM 		return (ret);
520110725SJohn.Forte@Sun.COM 
520210725SJohn.Forte@Sun.COM 	/*
520310725SJohn.Forte@Sun.COM 	 * Issue ioctl to get the stmf state
520410725SJohn.Forte@Sun.COM 	 */
520510725SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
520610725SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = sizeof (alua_state);
520710725SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&alua_state;
520810725SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_GET_ALUA_STATE, &stmfIoctl);
520910725SJohn.Forte@Sun.COM 
521010725SJohn.Forte@Sun.COM 	(void) close(fd);
521110725SJohn.Forte@Sun.COM 
521210725SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
521310725SJohn.Forte@Sun.COM 		switch (errno) {
521410725SJohn.Forte@Sun.COM 			case EBUSY:
521510725SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
521610725SJohn.Forte@Sun.COM 				break;
521710725SJohn.Forte@Sun.COM 			case EPERM:
521810725SJohn.Forte@Sun.COM 			case EACCES:
521910725SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
522010725SJohn.Forte@Sun.COM 				break;
522110725SJohn.Forte@Sun.COM 			default:
522210725SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
522310725SJohn.Forte@Sun.COM 				    "getStmfState:ioctl errno(%d)", errno);
522410725SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
522510725SJohn.Forte@Sun.COM 				break;
522610725SJohn.Forte@Sun.COM 		}
522710725SJohn.Forte@Sun.COM 	} else {
522810725SJohn.Forte@Sun.COM 		if (alua_state.alua_state == 1) {
522910725SJohn.Forte@Sun.COM 			*enabled = B_TRUE;
523010725SJohn.Forte@Sun.COM 		} else {
523110725SJohn.Forte@Sun.COM 			*enabled = B_FALSE;
523210725SJohn.Forte@Sun.COM 		}
523310725SJohn.Forte@Sun.COM 		*node = alua_state.alua_node;
523410725SJohn.Forte@Sun.COM 	}
523510725SJohn.Forte@Sun.COM 
523610725SJohn.Forte@Sun.COM 	return (ret);
523710725SJohn.Forte@Sun.COM }
523810725SJohn.Forte@Sun.COM 
523910725SJohn.Forte@Sun.COM /*
524010725SJohn.Forte@Sun.COM  * stmfSetAluaState
524110725SJohn.Forte@Sun.COM  *
524210725SJohn.Forte@Sun.COM  * Purpose - set the alua state to enabled/disabled
524310725SJohn.Forte@Sun.COM  *
524410725SJohn.Forte@Sun.COM  */
524510725SJohn.Forte@Sun.COM int
524610725SJohn.Forte@Sun.COM stmfSetAluaState(boolean_t enabled, uint32_t node)
524710725SJohn.Forte@Sun.COM {
524810725SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
524910725SJohn.Forte@Sun.COM 	int fd;
525010725SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl = {0};
525110725SJohn.Forte@Sun.COM 	stmf_alua_state_desc_t alua_state = {0};
525210725SJohn.Forte@Sun.COM 	int ioctlRet;
525310725SJohn.Forte@Sun.COM 
525410725SJohn.Forte@Sun.COM 	if ((enabled != B_TRUE && enabled != B_FALSE) || (node > 1)) {
525510725SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
525610725SJohn.Forte@Sun.COM 	}
525710725SJohn.Forte@Sun.COM 
525810725SJohn.Forte@Sun.COM 	if (enabled) {
525910725SJohn.Forte@Sun.COM 		alua_state.alua_state = 1;
526010725SJohn.Forte@Sun.COM 	}
526110725SJohn.Forte@Sun.COM 
526210725SJohn.Forte@Sun.COM 	alua_state.alua_node = node;
526310725SJohn.Forte@Sun.COM 
526410725SJohn.Forte@Sun.COM 	/*
526510725SJohn.Forte@Sun.COM 	 * Open control node for stmf
526610725SJohn.Forte@Sun.COM 	 */
526710725SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
526810725SJohn.Forte@Sun.COM 		return (ret);
526910725SJohn.Forte@Sun.COM 
527010725SJohn.Forte@Sun.COM 	/*
527110725SJohn.Forte@Sun.COM 	 * Issue ioctl to get the stmf state
527210725SJohn.Forte@Sun.COM 	 */
527310725SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
527410725SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (alua_state);
527510725SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&alua_state;
527610725SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_SET_ALUA_STATE, &stmfIoctl);
527710725SJohn.Forte@Sun.COM 
527810725SJohn.Forte@Sun.COM 	(void) close(fd);
527910725SJohn.Forte@Sun.COM 
528010725SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
528110725SJohn.Forte@Sun.COM 		switch (errno) {
528210725SJohn.Forte@Sun.COM 			case EBUSY:
528310725SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
528410725SJohn.Forte@Sun.COM 				break;
528510725SJohn.Forte@Sun.COM 			case EPERM:
528610725SJohn.Forte@Sun.COM 			case EACCES:
528710725SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
528810725SJohn.Forte@Sun.COM 				break;
528910725SJohn.Forte@Sun.COM 			default:
529010725SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
529110725SJohn.Forte@Sun.COM 				    "getStmfState:ioctl errno(%d)", errno);
529210725SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
529310725SJohn.Forte@Sun.COM 				break;
529410725SJohn.Forte@Sun.COM 		}
529510725SJohn.Forte@Sun.COM 	}
5296*11116SJohn.Forte@Sun.COM 	if (!enabled && ret == STMF_STATUS_SUCCESS) {
529710725SJohn.Forte@Sun.COM 		deleteNonActiveLus();
529810725SJohn.Forte@Sun.COM 	}
529910725SJohn.Forte@Sun.COM 
530010725SJohn.Forte@Sun.COM 	return (ret);
530110725SJohn.Forte@Sun.COM }
530210725SJohn.Forte@Sun.COM 
530310725SJohn.Forte@Sun.COM static void
530410725SJohn.Forte@Sun.COM deleteNonActiveLus()
530510725SJohn.Forte@Sun.COM {
530610725SJohn.Forte@Sun.COM 	int stmfRet;
530710725SJohn.Forte@Sun.COM 	int i;
530810725SJohn.Forte@Sun.COM 	stmfGuidList *luList;
530910725SJohn.Forte@Sun.COM 	luResource hdl = NULL;
531010725SJohn.Forte@Sun.COM 	char propVal[10];
531110725SJohn.Forte@Sun.COM 	size_t propValSize = sizeof (propVal);
531210725SJohn.Forte@Sun.COM 
531310725SJohn.Forte@Sun.COM 	stmfRet = stmfGetLogicalUnitList(&luList);
531410725SJohn.Forte@Sun.COM 	if (stmfRet != STMF_STATUS_SUCCESS) {
531510725SJohn.Forte@Sun.COM 		return;
531610725SJohn.Forte@Sun.COM 	}
531710725SJohn.Forte@Sun.COM 
531810725SJohn.Forte@Sun.COM 	for (i = 0; i < luList->cnt; i++) {
531910725SJohn.Forte@Sun.COM 		stmfRet = stmfGetLuResource(&luList->guid[i], &hdl);
532010725SJohn.Forte@Sun.COM 		if (stmfRet != STMF_STATUS_SUCCESS) {
532110725SJohn.Forte@Sun.COM 			goto err;
532210725SJohn.Forte@Sun.COM 		}
532310725SJohn.Forte@Sun.COM 		stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_ACCESS_STATE, propVal,
532410725SJohn.Forte@Sun.COM 		    &propValSize);
532510725SJohn.Forte@Sun.COM 		if (stmfRet != STMF_STATUS_SUCCESS) {
532610725SJohn.Forte@Sun.COM 			goto err;
532710725SJohn.Forte@Sun.COM 		}
532810725SJohn.Forte@Sun.COM 		if (propVal[0] == '0') {
532910725SJohn.Forte@Sun.COM 			(void) stmfFreeLuResource(hdl);
533010725SJohn.Forte@Sun.COM 			hdl = NULL;
533110725SJohn.Forte@Sun.COM 			continue;
533210725SJohn.Forte@Sun.COM 		}
533310725SJohn.Forte@Sun.COM 		(void) stmfDeleteLu(&luList->guid[i]);
533410725SJohn.Forte@Sun.COM 		(void) stmfFreeLuResource(hdl);
533510725SJohn.Forte@Sun.COM 		hdl = NULL;
533610725SJohn.Forte@Sun.COM 	}
533710725SJohn.Forte@Sun.COM 
533810725SJohn.Forte@Sun.COM err:
533910725SJohn.Forte@Sun.COM 	stmfFreeMemory(luList);
534010725SJohn.Forte@Sun.COM 	(void) stmfFreeLuResource(hdl);
534110725SJohn.Forte@Sun.COM }
534210725SJohn.Forte@Sun.COM 
534310725SJohn.Forte@Sun.COM /*
53447836SJohn.Forte@Sun.COM  * stmfLoadConfig
53457836SJohn.Forte@Sun.COM  *
53467836SJohn.Forte@Sun.COM  * Purpose - load the configuration data from smf into stmf
53477836SJohn.Forte@Sun.COM  *
53487836SJohn.Forte@Sun.COM  */
53497836SJohn.Forte@Sun.COM int
53507836SJohn.Forte@Sun.COM stmfLoadConfig(void)
53517836SJohn.Forte@Sun.COM {
53529585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
53537836SJohn.Forte@Sun.COM 	int fd;
53547836SJohn.Forte@Sun.COM 	stmf_state_desc_t stmfStateSet;
53557836SJohn.Forte@Sun.COM 	stmfState state;
53567836SJohn.Forte@Sun.COM 
53579585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
53589585STim.Szeto@Sun.COM 		stmfStateSet.state = STMF_STATE_OFFLINE;
535910560SSusan.Gleeson@Sun.COM 
53609585STim.Szeto@Sun.COM 		if ((ret = openStmf(OPEN_EXCL_STMF, &fd))
53619585STim.Szeto@Sun.COM 		    != STMF_STATUS_SUCCESS) {
53629585STim.Szeto@Sun.COM 			return (ret);
53639585STim.Szeto@Sun.COM 		}
536410560SSusan.Gleeson@Sun.COM 		/*
536510560SSusan.Gleeson@Sun.COM 		 * Configuration not stored persistently; nothing to
536610560SSusan.Gleeson@Sun.COM 		 * initialize so do not set to STMF_CONFIG_INIT.
536710560SSusan.Gleeson@Sun.COM 		 */
53689585STim.Szeto@Sun.COM 		stmfStateSet.config_state = STMF_CONFIG_INIT_DONE;
53699585STim.Szeto@Sun.COM 		goto done;
53709585STim.Szeto@Sun.COM 	}
53717836SJohn.Forte@Sun.COM 
53727836SJohn.Forte@Sun.COM 	/* Check to ensure service exists */
53737836SJohn.Forte@Sun.COM 	if (psCheckService() != STMF_STATUS_SUCCESS) {
53747836SJohn.Forte@Sun.COM 		return (STMF_ERROR_SERVICE_NOT_FOUND);
53757836SJohn.Forte@Sun.COM 	}
53767836SJohn.Forte@Sun.COM 
53777836SJohn.Forte@Sun.COM 	ret = stmfGetState(&state);
53787836SJohn.Forte@Sun.COM 	if (ret == STMF_STATUS_SUCCESS) {
53797836SJohn.Forte@Sun.COM 		if (state.operationalState != STMF_SERVICE_STATE_OFFLINE) {
53807836SJohn.Forte@Sun.COM 			return (STMF_ERROR_SERVICE_ONLINE);
53817836SJohn.Forte@Sun.COM 		}
53827836SJohn.Forte@Sun.COM 	} else {
53837836SJohn.Forte@Sun.COM 		return (STMF_STATUS_ERROR);
53847836SJohn.Forte@Sun.COM 	}
53857836SJohn.Forte@Sun.COM 
53867836SJohn.Forte@Sun.COM 
53877836SJohn.Forte@Sun.COM 	stmfStateSet.state = STMF_STATE_OFFLINE;
53887836SJohn.Forte@Sun.COM 	stmfStateSet.config_state = STMF_CONFIG_INIT;
53897836SJohn.Forte@Sun.COM 
53907836SJohn.Forte@Sun.COM 	/*
53917836SJohn.Forte@Sun.COM 	 * Open control node for stmf
53927836SJohn.Forte@Sun.COM 	 */
53937836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
53947836SJohn.Forte@Sun.COM 		return (ret);
53957836SJohn.Forte@Sun.COM 
53967836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE);
53977836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
53987836SJohn.Forte@Sun.COM 		goto done;
53997836SJohn.Forte@Sun.COM 	}
54007836SJohn.Forte@Sun.COM 
54017836SJohn.Forte@Sun.COM 	/* Load the persistent configuration data */
54027836SJohn.Forte@Sun.COM 	ret = loadStore(fd);
54037836SJohn.Forte@Sun.COM 	if (ret != 0) {
54047836SJohn.Forte@Sun.COM 		goto done;
54057836SJohn.Forte@Sun.COM 	}
54067836SJohn.Forte@Sun.COM 
54077836SJohn.Forte@Sun.COM 	stmfStateSet.state = STMF_STATE_OFFLINE;
54087836SJohn.Forte@Sun.COM 	stmfStateSet.config_state = STMF_CONFIG_INIT_DONE;
54097836SJohn.Forte@Sun.COM 
54107836SJohn.Forte@Sun.COM done:
54117836SJohn.Forte@Sun.COM 	if (ret == STMF_STATUS_SUCCESS) {
54127836SJohn.Forte@Sun.COM 		ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE);
54137836SJohn.Forte@Sun.COM 	}
54147836SJohn.Forte@Sun.COM 	(void) close(fd);
54157836SJohn.Forte@Sun.COM 	return (ret);
54167836SJohn.Forte@Sun.COM }
54177836SJohn.Forte@Sun.COM 
54189585STim.Szeto@Sun.COM 
54197836SJohn.Forte@Sun.COM /*
54207836SJohn.Forte@Sun.COM  * getStmfState
54217836SJohn.Forte@Sun.COM  *
54227836SJohn.Forte@Sun.COM  * stmfState - pointer to stmf_state_desc_t structure. Will contain the state
54237836SJohn.Forte@Sun.COM  *             information of the stmf service on success.
54247836SJohn.Forte@Sun.COM  */
54257836SJohn.Forte@Sun.COM static int
54267836SJohn.Forte@Sun.COM getStmfState(stmf_state_desc_t *stmfState)
54277836SJohn.Forte@Sun.COM {
54287836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
54297836SJohn.Forte@Sun.COM 	int fd;
54307836SJohn.Forte@Sun.COM 	int ioctlRet;
54317836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
54327836SJohn.Forte@Sun.COM 
54337836SJohn.Forte@Sun.COM 	/*
54347836SJohn.Forte@Sun.COM 	 * Open control node for stmf
54357836SJohn.Forte@Sun.COM 	 */
54367836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
54377836SJohn.Forte@Sun.COM 		return (ret);
54387836SJohn.Forte@Sun.COM 
54397836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
54407836SJohn.Forte@Sun.COM 	/*
54417836SJohn.Forte@Sun.COM 	 * Issue ioctl to get the stmf state
54427836SJohn.Forte@Sun.COM 	 */
54437836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
54447836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (stmf_state_desc_t);
54457836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)stmfState;
54467836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = sizeof (stmf_state_desc_t);
54477836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)stmfState;
54487836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_GET_STMF_STATE, &stmfIoctl);
54497836SJohn.Forte@Sun.COM 
54507836SJohn.Forte@Sun.COM 	(void) close(fd);
54517836SJohn.Forte@Sun.COM 
54527836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
54537836SJohn.Forte@Sun.COM 		switch (errno) {
54547836SJohn.Forte@Sun.COM 			case EBUSY:
54557836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
54567836SJohn.Forte@Sun.COM 				break;
54577836SJohn.Forte@Sun.COM 			case EPERM:
54587836SJohn.Forte@Sun.COM 			case EACCES:
54597836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
54607836SJohn.Forte@Sun.COM 				break;
54617836SJohn.Forte@Sun.COM 			default:
54627836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
54637836SJohn.Forte@Sun.COM 				    "getStmfState:ioctl errno(%d)", errno);
54647836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
54657836SJohn.Forte@Sun.COM 				break;
54667836SJohn.Forte@Sun.COM 		}
54677836SJohn.Forte@Sun.COM 	}
54687836SJohn.Forte@Sun.COM 	return (ret);
54697836SJohn.Forte@Sun.COM }
54707836SJohn.Forte@Sun.COM 
54717836SJohn.Forte@Sun.COM 
54727836SJohn.Forte@Sun.COM /*
54737836SJohn.Forte@Sun.COM  * setStmfState
54747836SJohn.Forte@Sun.COM  *
54757836SJohn.Forte@Sun.COM  * stmfState - pointer to caller set state structure
54767836SJohn.Forte@Sun.COM  * objectType - one of:
54777836SJohn.Forte@Sun.COM  *		LOGICAL_UNIT_TYPE
54787836SJohn.Forte@Sun.COM  *		TARGET_TYPE
54797836SJohn.Forte@Sun.COM  *		STMF_SERVICE_TYPE
54807836SJohn.Forte@Sun.COM  */
54817836SJohn.Forte@Sun.COM static int
54827836SJohn.Forte@Sun.COM setStmfState(int fd, stmf_state_desc_t *stmfState, int objectType)
54837836SJohn.Forte@Sun.COM {
54847836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
54857836SJohn.Forte@Sun.COM 	int ioctlRet;
54867836SJohn.Forte@Sun.COM 	int cmd;
54877836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
54887836SJohn.Forte@Sun.COM 
54897836SJohn.Forte@Sun.COM 	switch (objectType) {
54907836SJohn.Forte@Sun.COM 		case LOGICAL_UNIT_TYPE:
54917836SJohn.Forte@Sun.COM 			cmd = STMF_IOCTL_SET_LU_STATE;
54927836SJohn.Forte@Sun.COM 			break;
54937836SJohn.Forte@Sun.COM 		case TARGET_TYPE:
54947836SJohn.Forte@Sun.COM 			cmd = STMF_IOCTL_SET_TARGET_PORT_STATE;
54957836SJohn.Forte@Sun.COM 			break;
54967836SJohn.Forte@Sun.COM 		case STMF_SERVICE_TYPE:
54977836SJohn.Forte@Sun.COM 			cmd = STMF_IOCTL_SET_STMF_STATE;
54987836SJohn.Forte@Sun.COM 			break;
54997836SJohn.Forte@Sun.COM 		default:
55007836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
55017836SJohn.Forte@Sun.COM 			goto done;
55027836SJohn.Forte@Sun.COM 	}
55037836SJohn.Forte@Sun.COM 
55047836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
55057836SJohn.Forte@Sun.COM 	/*
55067836SJohn.Forte@Sun.COM 	 * Issue ioctl to set the stmf state
55077836SJohn.Forte@Sun.COM 	 */
55087836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
55097836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (stmf_state_desc_t);
55107836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)stmfState;
55117836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
55127836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
55137836SJohn.Forte@Sun.COM 		switch (errno) {
55147836SJohn.Forte@Sun.COM 			case EBUSY:
55157836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
55167836SJohn.Forte@Sun.COM 				break;
55179585STim.Szeto@Sun.COM 			case EPERM:
55187836SJohn.Forte@Sun.COM 			case EACCES:
55197836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
55207836SJohn.Forte@Sun.COM 				break;
55217836SJohn.Forte@Sun.COM 			case ENOENT:
55227836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
55237836SJohn.Forte@Sun.COM 				break;
55247836SJohn.Forte@Sun.COM 			default:
55257836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
55267836SJohn.Forte@Sun.COM 				    "setStmfState:ioctl errno(%d)", errno);
55277836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
55287836SJohn.Forte@Sun.COM 				break;
55297836SJohn.Forte@Sun.COM 		}
55307836SJohn.Forte@Sun.COM 	}
55317836SJohn.Forte@Sun.COM done:
55327836SJohn.Forte@Sun.COM 	return (ret);
55337836SJohn.Forte@Sun.COM }
55347836SJohn.Forte@Sun.COM 
55357836SJohn.Forte@Sun.COM /*
55367836SJohn.Forte@Sun.COM  * stmfOnline
55377836SJohn.Forte@Sun.COM  *
55387836SJohn.Forte@Sun.COM  * Purpose: Online stmf service
55397836SJohn.Forte@Sun.COM  *
55407836SJohn.Forte@Sun.COM  */
55417836SJohn.Forte@Sun.COM int
55427836SJohn.Forte@Sun.COM stmfOnline(void)
55437836SJohn.Forte@Sun.COM {
55447836SJohn.Forte@Sun.COM 	int ret;
55457836SJohn.Forte@Sun.COM 	int fd;
55467836SJohn.Forte@Sun.COM 	stmfState state;
55477836SJohn.Forte@Sun.COM 	stmf_state_desc_t iState;
55487836SJohn.Forte@Sun.COM 
55497836SJohn.Forte@Sun.COM 	ret = stmfGetState(&state);
55507836SJohn.Forte@Sun.COM 	if (ret == STMF_STATUS_SUCCESS) {
55517836SJohn.Forte@Sun.COM 		if (state.operationalState == STMF_SERVICE_STATE_ONLINE) {
55527836SJohn.Forte@Sun.COM 			return (STMF_ERROR_SERVICE_ONLINE);
55537836SJohn.Forte@Sun.COM 		}
55547836SJohn.Forte@Sun.COM 	} else {
55557836SJohn.Forte@Sun.COM 		return (STMF_STATUS_ERROR);
55567836SJohn.Forte@Sun.COM 	}
55577836SJohn.Forte@Sun.COM 	iState.state = STMF_STATE_ONLINE;
55587836SJohn.Forte@Sun.COM 	iState.config_state = STMF_CONFIG_NONE;
55597836SJohn.Forte@Sun.COM 	/*
55607836SJohn.Forte@Sun.COM 	 * Open control node for stmf
55617836SJohn.Forte@Sun.COM 	 * to make call to setStmfState()
55627836SJohn.Forte@Sun.COM 	 */
55637836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
55647836SJohn.Forte@Sun.COM 		return (ret);
55657836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &iState, STMF_SERVICE_TYPE);
55667836SJohn.Forte@Sun.COM 	(void) close(fd);
55677836SJohn.Forte@Sun.COM 	return (ret);
55687836SJohn.Forte@Sun.COM }
55697836SJohn.Forte@Sun.COM 
55707836SJohn.Forte@Sun.COM /*
55717836SJohn.Forte@Sun.COM  * stmfOffline
55727836SJohn.Forte@Sun.COM  *
55737836SJohn.Forte@Sun.COM  * Purpose: Offline stmf service
55747836SJohn.Forte@Sun.COM  *
55757836SJohn.Forte@Sun.COM  */
55767836SJohn.Forte@Sun.COM int
55777836SJohn.Forte@Sun.COM stmfOffline(void)
55787836SJohn.Forte@Sun.COM {
55797836SJohn.Forte@Sun.COM 	int ret;
55807836SJohn.Forte@Sun.COM 	int fd;
55817836SJohn.Forte@Sun.COM 	stmfState state;
55827836SJohn.Forte@Sun.COM 	stmf_state_desc_t iState;
55837836SJohn.Forte@Sun.COM 
55847836SJohn.Forte@Sun.COM 	ret = stmfGetState(&state);
55857836SJohn.Forte@Sun.COM 	if (ret == STMF_STATUS_SUCCESS) {
55867836SJohn.Forte@Sun.COM 		if (state.operationalState == STMF_SERVICE_STATE_OFFLINE) {
55877836SJohn.Forte@Sun.COM 			return (STMF_ERROR_SERVICE_OFFLINE);
55887836SJohn.Forte@Sun.COM 		}
55897836SJohn.Forte@Sun.COM 	} else {
55907836SJohn.Forte@Sun.COM 		return (STMF_STATUS_ERROR);
55917836SJohn.Forte@Sun.COM 	}
55927836SJohn.Forte@Sun.COM 	iState.state = STMF_STATE_OFFLINE;
55937836SJohn.Forte@Sun.COM 	iState.config_state = STMF_CONFIG_NONE;
55947836SJohn.Forte@Sun.COM 
55957836SJohn.Forte@Sun.COM 	/*
55967836SJohn.Forte@Sun.COM 	 * Open control node for stmf
55977836SJohn.Forte@Sun.COM 	 * to make call to setStmfState()
55987836SJohn.Forte@Sun.COM 	 */
55997836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
56007836SJohn.Forte@Sun.COM 		return (ret);
56017836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &iState, STMF_SERVICE_TYPE);
56027836SJohn.Forte@Sun.COM 	(void) close(fd);
56037836SJohn.Forte@Sun.COM 	return (ret);
56047836SJohn.Forte@Sun.COM }
56057836SJohn.Forte@Sun.COM 
56067836SJohn.Forte@Sun.COM 
56077836SJohn.Forte@Sun.COM /*
56087836SJohn.Forte@Sun.COM  * stmfOfflineTarget
56097836SJohn.Forte@Sun.COM  *
56107836SJohn.Forte@Sun.COM  * Purpose: Change state of target to offline
56117836SJohn.Forte@Sun.COM  *
56127836SJohn.Forte@Sun.COM  * devid - devid of the target to offline
56137836SJohn.Forte@Sun.COM  */
56147836SJohn.Forte@Sun.COM int
56157836SJohn.Forte@Sun.COM stmfOfflineTarget(stmfDevid *devid)
56167836SJohn.Forte@Sun.COM {
56177836SJohn.Forte@Sun.COM 	stmf_state_desc_t targetState;
56187836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
56197836SJohn.Forte@Sun.COM 	int fd;
56207836SJohn.Forte@Sun.COM 
56217836SJohn.Forte@Sun.COM 	if (devid == NULL) {
56227836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
56237836SJohn.Forte@Sun.COM 	}
56247836SJohn.Forte@Sun.COM 	bzero(&targetState, sizeof (targetState));
56257836SJohn.Forte@Sun.COM 
56267836SJohn.Forte@Sun.COM 	targetState.state = STMF_STATE_OFFLINE;
56277836SJohn.Forte@Sun.COM 	targetState.ident[IDENT_LENGTH_BYTE] = devid->identLength;
56287836SJohn.Forte@Sun.COM 	bcopy(&(devid->ident), &targetState.ident[IDENT_LENGTH_BYTE + 1],
56297836SJohn.Forte@Sun.COM 	    devid->identLength);
56307836SJohn.Forte@Sun.COM 	/*
56317836SJohn.Forte@Sun.COM 	 * Open control node for stmf
56327836SJohn.Forte@Sun.COM 	 * to make call to setStmfState()
56337836SJohn.Forte@Sun.COM 	 */
56347836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
56357836SJohn.Forte@Sun.COM 		return (ret);
56367836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &targetState, TARGET_TYPE);
56377836SJohn.Forte@Sun.COM 	(void) close(fd);
56387836SJohn.Forte@Sun.COM 	return (ret);
56397836SJohn.Forte@Sun.COM }
56407836SJohn.Forte@Sun.COM 
56417836SJohn.Forte@Sun.COM /*
56427836SJohn.Forte@Sun.COM  * stmfOfflineLogicalUnit
56437836SJohn.Forte@Sun.COM  *
56447836SJohn.Forte@Sun.COM  * Purpose: Change state of logical unit to offline
56457836SJohn.Forte@Sun.COM  *
56467836SJohn.Forte@Sun.COM  * lu - guid of the logical unit to offline
56477836SJohn.Forte@Sun.COM  */
56487836SJohn.Forte@Sun.COM int
56497836SJohn.Forte@Sun.COM stmfOfflineLogicalUnit(stmfGuid *lu)
56507836SJohn.Forte@Sun.COM {
56517836SJohn.Forte@Sun.COM 	stmf_state_desc_t luState;
56527836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
56537836SJohn.Forte@Sun.COM 	int fd;
56547836SJohn.Forte@Sun.COM 
56557836SJohn.Forte@Sun.COM 	if (lu == NULL) {
56567836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
56577836SJohn.Forte@Sun.COM 	}
56587836SJohn.Forte@Sun.COM 
56597836SJohn.Forte@Sun.COM 	bzero(&luState, sizeof (luState));
56607836SJohn.Forte@Sun.COM 
56617836SJohn.Forte@Sun.COM 	luState.state = STMF_STATE_OFFLINE;
56627836SJohn.Forte@Sun.COM 	bcopy(lu, &luState.ident, sizeof (stmfGuid));
56637836SJohn.Forte@Sun.COM 	/*
56647836SJohn.Forte@Sun.COM 	 * Open control node for stmf
56657836SJohn.Forte@Sun.COM 	 * to make call to setStmfState()
56667836SJohn.Forte@Sun.COM 	 */
56677836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
56687836SJohn.Forte@Sun.COM 		return (ret);
56697836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &luState, LOGICAL_UNIT_TYPE);
56707836SJohn.Forte@Sun.COM 	(void) close(fd);
56717836SJohn.Forte@Sun.COM 	return (ret);
56727836SJohn.Forte@Sun.COM }
56737836SJohn.Forte@Sun.COM 
56747836SJohn.Forte@Sun.COM /*
56757836SJohn.Forte@Sun.COM  * stmfOnlineTarget
56767836SJohn.Forte@Sun.COM  *
56777836SJohn.Forte@Sun.COM  * Purpose: Change state of target to online
56787836SJohn.Forte@Sun.COM  *
56797836SJohn.Forte@Sun.COM  * devid - devid of the target to online
56807836SJohn.Forte@Sun.COM  */
56817836SJohn.Forte@Sun.COM int
56827836SJohn.Forte@Sun.COM stmfOnlineTarget(stmfDevid *devid)
56837836SJohn.Forte@Sun.COM {
56847836SJohn.Forte@Sun.COM 	stmf_state_desc_t targetState;
56857836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
56867836SJohn.Forte@Sun.COM 	int fd;
56877836SJohn.Forte@Sun.COM 
56887836SJohn.Forte@Sun.COM 	if (devid == NULL) {
56897836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
56907836SJohn.Forte@Sun.COM 	}
56917836SJohn.Forte@Sun.COM 	bzero(&targetState, sizeof (targetState));
56927836SJohn.Forte@Sun.COM 
56937836SJohn.Forte@Sun.COM 	targetState.state = STMF_STATE_ONLINE;
56947836SJohn.Forte@Sun.COM 	targetState.ident[IDENT_LENGTH_BYTE] = devid->identLength;
56957836SJohn.Forte@Sun.COM 	bcopy(&(devid->ident), &targetState.ident[IDENT_LENGTH_BYTE + 1],
56967836SJohn.Forte@Sun.COM 	    devid->identLength);
56977836SJohn.Forte@Sun.COM 	/*
56987836SJohn.Forte@Sun.COM 	 * Open control node for stmf
56997836SJohn.Forte@Sun.COM 	 * to make call to setStmfState()
57007836SJohn.Forte@Sun.COM 	 */
57017836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
57027836SJohn.Forte@Sun.COM 		return (ret);
57037836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &targetState, TARGET_TYPE);
57047836SJohn.Forte@Sun.COM 	(void) close(fd);
57057836SJohn.Forte@Sun.COM 	return (ret);
57067836SJohn.Forte@Sun.COM }
57077836SJohn.Forte@Sun.COM 
57087836SJohn.Forte@Sun.COM /*
57097836SJohn.Forte@Sun.COM  * stmfOnlineLogicalUnit
57107836SJohn.Forte@Sun.COM  *
57117836SJohn.Forte@Sun.COM  * Purpose: Change state of logical unit to online
57127836SJohn.Forte@Sun.COM  *
57137836SJohn.Forte@Sun.COM  * lu - guid of the logical unit to online
57147836SJohn.Forte@Sun.COM  */
57157836SJohn.Forte@Sun.COM int
57167836SJohn.Forte@Sun.COM stmfOnlineLogicalUnit(stmfGuid *lu)
57177836SJohn.Forte@Sun.COM {
57187836SJohn.Forte@Sun.COM 	stmf_state_desc_t luState;
57197836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
57207836SJohn.Forte@Sun.COM 	int fd;
57217836SJohn.Forte@Sun.COM 
57227836SJohn.Forte@Sun.COM 	if (lu == NULL) {
57237836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
57247836SJohn.Forte@Sun.COM 	}
57257836SJohn.Forte@Sun.COM 
57267836SJohn.Forte@Sun.COM 	bzero(&luState, sizeof (luState));
57277836SJohn.Forte@Sun.COM 
57287836SJohn.Forte@Sun.COM 	luState.state = STMF_STATE_ONLINE;
57297836SJohn.Forte@Sun.COM 	bcopy(lu, &luState.ident, sizeof (stmfGuid));
57307836SJohn.Forte@Sun.COM 	/*
57317836SJohn.Forte@Sun.COM 	 * Open control node for stmf
57327836SJohn.Forte@Sun.COM 	 * to make call to setStmfState()
57337836SJohn.Forte@Sun.COM 	 */
57347836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
57357836SJohn.Forte@Sun.COM 		return (ret);
57367836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &luState, LOGICAL_UNIT_TYPE);
57377836SJohn.Forte@Sun.COM 	(void) close(fd);
57387836SJohn.Forte@Sun.COM 	return (ret);
57397836SJohn.Forte@Sun.COM }
57407836SJohn.Forte@Sun.COM 
57417836SJohn.Forte@Sun.COM /*
57427836SJohn.Forte@Sun.COM  * stmfRemoveFromHostGroup
57437836SJohn.Forte@Sun.COM  *
57447836SJohn.Forte@Sun.COM  * Purpose: Removes an initiator from an initiator group
57457836SJohn.Forte@Sun.COM  *
57467836SJohn.Forte@Sun.COM  * hostGroupName - name of an initiator group
57477836SJohn.Forte@Sun.COM  * hostName - name of host group member to remove
57487836SJohn.Forte@Sun.COM  */
57497836SJohn.Forte@Sun.COM int
57507836SJohn.Forte@Sun.COM stmfRemoveFromHostGroup(stmfGroupName *hostGroupName, stmfDevid *hostName)
57517836SJohn.Forte@Sun.COM {
57527836SJohn.Forte@Sun.COM 	int ret;
57537836SJohn.Forte@Sun.COM 	int fd;
57547836SJohn.Forte@Sun.COM 
57557836SJohn.Forte@Sun.COM 	if (hostGroupName == NULL ||
57567836SJohn.Forte@Sun.COM 	    (strnlen((char *)hostGroupName, sizeof (stmfGroupName))
57577836SJohn.Forte@Sun.COM 	    == sizeof (stmfGroupName)) || hostName == NULL) {
57587836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
57597836SJohn.Forte@Sun.COM 	}
57607836SJohn.Forte@Sun.COM 
57617836SJohn.Forte@Sun.COM 	/* call init */
57627836SJohn.Forte@Sun.COM 	ret = initializeConfig();
57637836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
57647836SJohn.Forte@Sun.COM 		return (ret);
57657836SJohn.Forte@Sun.COM 	}
57667836SJohn.Forte@Sun.COM 
57677836SJohn.Forte@Sun.COM 	/*
57687836SJohn.Forte@Sun.COM 	 * Open control node for stmf
57697836SJohn.Forte@Sun.COM 	 */
57707836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
57717836SJohn.Forte@Sun.COM 		return (ret);
57727836SJohn.Forte@Sun.COM 
57737836SJohn.Forte@Sun.COM 	if ((ret = groupMemberIoctl(fd, STMF_IOCTL_REMOVE_HG_ENTRY,
57747836SJohn.Forte@Sun.COM 	    hostGroupName, hostName)) != STMF_STATUS_SUCCESS) {
57757836SJohn.Forte@Sun.COM 		goto done;
57767836SJohn.Forte@Sun.COM 	}
57777836SJohn.Forte@Sun.COM 
57789585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
57799585STim.Szeto@Sun.COM 		goto done;
57809585STim.Szeto@Sun.COM 	}
57819585STim.Szeto@Sun.COM 
57827836SJohn.Forte@Sun.COM 	ret = psRemoveHostGroupMember((char *)hostGroupName,
57837836SJohn.Forte@Sun.COM 	    (char *)hostName->ident);
57847836SJohn.Forte@Sun.COM 	switch (ret) {
57857836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
57867836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
57877836SJohn.Forte@Sun.COM 			break;
57887836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_MEMBER_NOT_FOUND:
57897836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_MEMBER_NOT_FOUND;
57907836SJohn.Forte@Sun.COM 			break;
57917836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_GROUP_NOT_FOUND:
57927836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_GROUP_NOT_FOUND;
57937836SJohn.Forte@Sun.COM 			break;
57947836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
57957836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
57967836SJohn.Forte@Sun.COM 			break;
57977836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
57987836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
57997836SJohn.Forte@Sun.COM 			break;
58007836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
58017836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
58027836SJohn.Forte@Sun.COM 			break;
58037836SJohn.Forte@Sun.COM 		default:
58047836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
58057836SJohn.Forte@Sun.COM 			    "stmfRemoveFromHostGroup"
58067836SJohn.Forte@Sun.COM 			    "psRemoveHostGroupMember:error(%d)", ret);
58077836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
58087836SJohn.Forte@Sun.COM 			break;
58097836SJohn.Forte@Sun.COM 	}
58107836SJohn.Forte@Sun.COM 
58117836SJohn.Forte@Sun.COM done:
58127836SJohn.Forte@Sun.COM 	(void) close(fd);
58137836SJohn.Forte@Sun.COM 	return (ret);
58147836SJohn.Forte@Sun.COM }
58157836SJohn.Forte@Sun.COM 
58167836SJohn.Forte@Sun.COM /*
58177836SJohn.Forte@Sun.COM  * stmfRemoveFromTargetGroup
58187836SJohn.Forte@Sun.COM  *
58197836SJohn.Forte@Sun.COM  * Purpose: Removes a local port from a local port group
58207836SJohn.Forte@Sun.COM  *
58217836SJohn.Forte@Sun.COM  * targetGroupName - name of a target group
58227836SJohn.Forte@Sun.COM  * targetName - name of target to remove
58237836SJohn.Forte@Sun.COM  */
58247836SJohn.Forte@Sun.COM int
58257836SJohn.Forte@Sun.COM stmfRemoveFromTargetGroup(stmfGroupName *targetGroupName, stmfDevid *targetName)
58267836SJohn.Forte@Sun.COM {
58277836SJohn.Forte@Sun.COM 	int ret;
58287836SJohn.Forte@Sun.COM 	int fd;
58297836SJohn.Forte@Sun.COM 
58307836SJohn.Forte@Sun.COM 	if (targetGroupName == NULL ||
58317836SJohn.Forte@Sun.COM 	    (strnlen((char *)targetGroupName, sizeof (stmfGroupName))
58327836SJohn.Forte@Sun.COM 	    == sizeof (stmfGroupName)) || targetName == NULL) {
58337836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
58347836SJohn.Forte@Sun.COM 	}
58357836SJohn.Forte@Sun.COM 
58367836SJohn.Forte@Sun.COM 	/* call init */
58377836SJohn.Forte@Sun.COM 	ret = initializeConfig();
58387836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
58397836SJohn.Forte@Sun.COM 		return (ret);
58407836SJohn.Forte@Sun.COM 	}
58417836SJohn.Forte@Sun.COM 
58427836SJohn.Forte@Sun.COM 	/*
58437836SJohn.Forte@Sun.COM 	 * Open control node for stmf
58447836SJohn.Forte@Sun.COM 	 */
58457836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
58467836SJohn.Forte@Sun.COM 		return (ret);
58477836SJohn.Forte@Sun.COM 
58487836SJohn.Forte@Sun.COM 	if ((ret = groupMemberIoctl(fd, STMF_IOCTL_REMOVE_TG_ENTRY,
58497836SJohn.Forte@Sun.COM 	    targetGroupName, targetName)) != STMF_STATUS_SUCCESS) {
58507836SJohn.Forte@Sun.COM 		goto done;
58517836SJohn.Forte@Sun.COM 	}
58527836SJohn.Forte@Sun.COM 
58539585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
58549585STim.Szeto@Sun.COM 		goto done;
58559585STim.Szeto@Sun.COM 	}
58569585STim.Szeto@Sun.COM 
58577836SJohn.Forte@Sun.COM 	ret = psRemoveTargetGroupMember((char *)targetGroupName,
58587836SJohn.Forte@Sun.COM 	    (char *)targetName->ident);
58597836SJohn.Forte@Sun.COM 	switch (ret) {
58607836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
58617836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
58627836SJohn.Forte@Sun.COM 			break;
58637836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_MEMBER_NOT_FOUND:
58647836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_MEMBER_NOT_FOUND;
58657836SJohn.Forte@Sun.COM 			break;
58667836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_GROUP_NOT_FOUND:
58677836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_GROUP_NOT_FOUND;
58687836SJohn.Forte@Sun.COM 			break;
58697836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
58707836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
58717836SJohn.Forte@Sun.COM 			break;
58727836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
58737836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
58747836SJohn.Forte@Sun.COM 			break;
58757836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
58767836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
58777836SJohn.Forte@Sun.COM 			break;
58787836SJohn.Forte@Sun.COM 		default:
58797836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
58807836SJohn.Forte@Sun.COM 			    "stmfRemoveFromTargetGroup"
58817836SJohn.Forte@Sun.COM 			    "psRemoveTargetGroupMember:error(%d)", ret);
58827836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
58837836SJohn.Forte@Sun.COM 			break;
58847836SJohn.Forte@Sun.COM 	}
58857836SJohn.Forte@Sun.COM 
58867836SJohn.Forte@Sun.COM done:
58877836SJohn.Forte@Sun.COM 	(void) close(fd);
58887836SJohn.Forte@Sun.COM 	return (ret);
58897836SJohn.Forte@Sun.COM }
58907836SJohn.Forte@Sun.COM 
58917836SJohn.Forte@Sun.COM /*
58927836SJohn.Forte@Sun.COM  * stmfRemoveViewEntry
58937836SJohn.Forte@Sun.COM  *
58947836SJohn.Forte@Sun.COM  * Purpose: Removes a view entry from a logical unit
58957836SJohn.Forte@Sun.COM  *
58967836SJohn.Forte@Sun.COM  * lu - guid of lu for which view entry is being removed
58977836SJohn.Forte@Sun.COM  * viewEntryIndex - index of view entry to remove
58987836SJohn.Forte@Sun.COM  *
58997836SJohn.Forte@Sun.COM  */
59007836SJohn.Forte@Sun.COM int
59017836SJohn.Forte@Sun.COM stmfRemoveViewEntry(stmfGuid *lu, uint32_t viewEntryIndex)
59027836SJohn.Forte@Sun.COM {
59037836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
59047836SJohn.Forte@Sun.COM 	int fd;
59057836SJohn.Forte@Sun.COM 	int ioctlRet;
59067836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
59077836SJohn.Forte@Sun.COM 	stmf_view_op_entry_t ioctlViewEntry;
59087836SJohn.Forte@Sun.COM 
59097836SJohn.Forte@Sun.COM 	if (lu == NULL) {
59107836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
59117836SJohn.Forte@Sun.COM 	}
59127836SJohn.Forte@Sun.COM 
59137836SJohn.Forte@Sun.COM 	/* call init */
59147836SJohn.Forte@Sun.COM 	ret = initializeConfig();
59157836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
59167836SJohn.Forte@Sun.COM 		return (ret);
59177836SJohn.Forte@Sun.COM 	}
59187836SJohn.Forte@Sun.COM 
59197836SJohn.Forte@Sun.COM 	/*
59207836SJohn.Forte@Sun.COM 	 * Open control node for stmf
59217836SJohn.Forte@Sun.COM 	 */
59227836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
59237836SJohn.Forte@Sun.COM 		return (ret);
59247836SJohn.Forte@Sun.COM 
59257836SJohn.Forte@Sun.COM 	bzero(&ioctlViewEntry, sizeof (ioctlViewEntry));
59267836SJohn.Forte@Sun.COM 	ioctlViewEntry.ve_ndx_valid = B_TRUE;
59277836SJohn.Forte@Sun.COM 	ioctlViewEntry.ve_ndx = viewEntryIndex;
59287836SJohn.Forte@Sun.COM 	bcopy(lu, &ioctlViewEntry.ve_guid, sizeof (stmfGuid));
59297836SJohn.Forte@Sun.COM 
59307836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
59317836SJohn.Forte@Sun.COM 	/*
59327836SJohn.Forte@Sun.COM 	 * Issue ioctl to add to the view entry
59337836SJohn.Forte@Sun.COM 	 */
59347836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
59357836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry);
59367836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry;
59377836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_REMOVE_VIEW_ENTRY, &stmfIoctl);
59387836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
59397836SJohn.Forte@Sun.COM 		switch (errno) {
59407836SJohn.Forte@Sun.COM 			case EBUSY:
59417836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
59427836SJohn.Forte@Sun.COM 				break;
59439585STim.Szeto@Sun.COM 			case EPERM:
59449585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
59459585STim.Szeto@Sun.COM 				break;
59467836SJohn.Forte@Sun.COM 			case EACCES:
59477836SJohn.Forte@Sun.COM 				switch (stmfIoctl.stmf_error) {
59487836SJohn.Forte@Sun.COM 					case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
59497836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_CONFIG_NONE;
59507836SJohn.Forte@Sun.COM 						break;
59517836SJohn.Forte@Sun.COM 					default:
59527836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_PERM;
59537836SJohn.Forte@Sun.COM 						break;
59547836SJohn.Forte@Sun.COM 				}
59557836SJohn.Forte@Sun.COM 				break;
59567836SJohn.Forte@Sun.COM 			case ENODEV:
59577836SJohn.Forte@Sun.COM 			case ENOENT:
59587836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
59597836SJohn.Forte@Sun.COM 				break;
59607836SJohn.Forte@Sun.COM 			default:
59617836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
59627836SJohn.Forte@Sun.COM 				    "stmfRemoveViewEntry:ioctl errno(%d)",
59637836SJohn.Forte@Sun.COM 				    errno);
59647836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
59657836SJohn.Forte@Sun.COM 				break;
59667836SJohn.Forte@Sun.COM 		}
59677836SJohn.Forte@Sun.COM 		goto done;
59687836SJohn.Forte@Sun.COM 	}
59697836SJohn.Forte@Sun.COM 
59709585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
59719585STim.Szeto@Sun.COM 		goto done;
59729585STim.Szeto@Sun.COM 	}
59739585STim.Szeto@Sun.COM 
59747836SJohn.Forte@Sun.COM 	ret = psRemoveViewEntry(lu, viewEntryIndex);
59757836SJohn.Forte@Sun.COM 	switch (ret) {
59767836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
59777836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
59787836SJohn.Forte@Sun.COM 			break;
59797836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
59807836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
59817836SJohn.Forte@Sun.COM 			break;
59827836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
59837836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
59847836SJohn.Forte@Sun.COM 			break;
59857836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
59867836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
59877836SJohn.Forte@Sun.COM 			break;
59887836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
59897836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
59907836SJohn.Forte@Sun.COM 			break;
59917836SJohn.Forte@Sun.COM 		default:
59927836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
59937836SJohn.Forte@Sun.COM 			    "stmfRemoveViewEntry" "psRemoveViewEntry:error(%d)",
59947836SJohn.Forte@Sun.COM 			    ret);
59957836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
59967836SJohn.Forte@Sun.COM 			break;
59977836SJohn.Forte@Sun.COM 	}
59987836SJohn.Forte@Sun.COM 
59997836SJohn.Forte@Sun.COM done:
60007836SJohn.Forte@Sun.COM 	(void) close(fd);
60017836SJohn.Forte@Sun.COM 	return (ret);
60027836SJohn.Forte@Sun.COM }
60037836SJohn.Forte@Sun.COM 
60047836SJohn.Forte@Sun.COM /*
60057836SJohn.Forte@Sun.COM  * stmfSetProviderData
60067836SJohn.Forte@Sun.COM  *
60077836SJohn.Forte@Sun.COM  * Purpose: set the provider data
60087836SJohn.Forte@Sun.COM  *
60097836SJohn.Forte@Sun.COM  * providerName - unique name of provider
60107836SJohn.Forte@Sun.COM  * nvl - nvlist to set
60117836SJohn.Forte@Sun.COM  * providerType - type of provider for which to set data
60127836SJohn.Forte@Sun.COM  *		STMF_LU_PROVIDER_TYPE
60137836SJohn.Forte@Sun.COM  *		STMF_PORT_PROVIDER_TYPE
60147836SJohn.Forte@Sun.COM  */
60157836SJohn.Forte@Sun.COM int
60167836SJohn.Forte@Sun.COM stmfSetProviderData(char *providerName, nvlist_t *nvl, int providerType)
60177836SJohn.Forte@Sun.COM {
60187836SJohn.Forte@Sun.COM 	return (stmfSetProviderDataProt(providerName, nvl, providerType,
60197836SJohn.Forte@Sun.COM 	    NULL));
60207836SJohn.Forte@Sun.COM }
60217836SJohn.Forte@Sun.COM 
60227836SJohn.Forte@Sun.COM /*
60237836SJohn.Forte@Sun.COM  * stmfSetProviderDataProt
60247836SJohn.Forte@Sun.COM  *
60257836SJohn.Forte@Sun.COM  * Purpose: set the provider data
60267836SJohn.Forte@Sun.COM  *
60277836SJohn.Forte@Sun.COM  * providerName - unique name of provider
60287836SJohn.Forte@Sun.COM  * nvl - nvlist to set
60297836SJohn.Forte@Sun.COM  * providerType - type of provider for which to set data
60307836SJohn.Forte@Sun.COM  *		STMF_LU_PROVIDER_TYPE
60317836SJohn.Forte@Sun.COM  *		STMF_PORT_PROVIDER_TYPE
60327836SJohn.Forte@Sun.COM  * setToken - Stale data token returned in the stmfGetProviderDataProt()
60337836SJohn.Forte@Sun.COM  *	      call or NULL.
60347836SJohn.Forte@Sun.COM  */
60357836SJohn.Forte@Sun.COM int
60367836SJohn.Forte@Sun.COM stmfSetProviderDataProt(char *providerName, nvlist_t *nvl, int providerType,
60377836SJohn.Forte@Sun.COM     uint64_t *setToken)
60387836SJohn.Forte@Sun.COM {
60397836SJohn.Forte@Sun.COM 	int ret;
60407836SJohn.Forte@Sun.COM 	int fd;
60417836SJohn.Forte@Sun.COM 
60427836SJohn.Forte@Sun.COM 	if (providerName == NULL || nvl == NULL) {
60437836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
60447836SJohn.Forte@Sun.COM 	}
60457836SJohn.Forte@Sun.COM 
60467836SJohn.Forte@Sun.COM 	if (providerType != STMF_LU_PROVIDER_TYPE &&
60477836SJohn.Forte@Sun.COM 	    providerType != STMF_PORT_PROVIDER_TYPE) {
60487836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
60497836SJohn.Forte@Sun.COM 	}
60507836SJohn.Forte@Sun.COM 
60517836SJohn.Forte@Sun.COM 	/* call init */
60527836SJohn.Forte@Sun.COM 	ret = initializeConfig();
60537836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
60547836SJohn.Forte@Sun.COM 		return (ret);
60557836SJohn.Forte@Sun.COM 	}
60567836SJohn.Forte@Sun.COM 
60577836SJohn.Forte@Sun.COM 	/*
60587836SJohn.Forte@Sun.COM 	 * Open control node for stmf
60597836SJohn.Forte@Sun.COM 	 */
60607836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
60617836SJohn.Forte@Sun.COM 		return (ret);
60627836SJohn.Forte@Sun.COM 
60639585STim.Szeto@Sun.COM 	ret = setProviderData(fd, providerName, nvl, providerType, setToken);
60647836SJohn.Forte@Sun.COM 
60657836SJohn.Forte@Sun.COM 	(void) close(fd);
60667836SJohn.Forte@Sun.COM 
60677836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
60687836SJohn.Forte@Sun.COM 		goto done;
60697836SJohn.Forte@Sun.COM 	}
60707836SJohn.Forte@Sun.COM 
60719585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
60729585STim.Szeto@Sun.COM 		goto done;
60739585STim.Szeto@Sun.COM 	}
60749585STim.Szeto@Sun.COM 
60757836SJohn.Forte@Sun.COM 	/* setting driver provider data successful. Now persist it */
60769585STim.Szeto@Sun.COM 	ret = psSetProviderData(providerName, nvl, providerType, NULL);
60777836SJohn.Forte@Sun.COM 	switch (ret) {
60787836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
60797836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
60807836SJohn.Forte@Sun.COM 			break;
60817836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_EXISTS:
60827836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_EXISTS;
60837836SJohn.Forte@Sun.COM 			break;
60847836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
60857836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
60867836SJohn.Forte@Sun.COM 			break;
60877836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
60887836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
60897836SJohn.Forte@Sun.COM 			break;
60907836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
60917836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
60927836SJohn.Forte@Sun.COM 			break;
60937836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_PROV_DATA_STALE:
60947836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_PROV_DATA_STALE;
60957836SJohn.Forte@Sun.COM 			break;
60967836SJohn.Forte@Sun.COM 		default:
60977836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
60987836SJohn.Forte@Sun.COM 			    "stmfSetProviderData"
60997836SJohn.Forte@Sun.COM 			    "psSetProviderData:error(%d)", ret);
61007836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
61017836SJohn.Forte@Sun.COM 			break;
61027836SJohn.Forte@Sun.COM 	}
61037836SJohn.Forte@Sun.COM 
61047836SJohn.Forte@Sun.COM done:
61057836SJohn.Forte@Sun.COM 	return (ret);
61067836SJohn.Forte@Sun.COM }
61077836SJohn.Forte@Sun.COM 
61087836SJohn.Forte@Sun.COM /*
61099585STim.Szeto@Sun.COM  * getProviderData
61109585STim.Szeto@Sun.COM  *
61119585STim.Szeto@Sun.COM  * Purpose: set the provider data from stmf
61129585STim.Szeto@Sun.COM  *
61139585STim.Szeto@Sun.COM  * providerName - unique name of provider
61149585STim.Szeto@Sun.COM  * nvl - nvlist to load/retrieve
61159585STim.Szeto@Sun.COM  * providerType - logical unit or port provider
61169585STim.Szeto@Sun.COM  * setToken - returned stale data token
61179585STim.Szeto@Sun.COM  */
61189585STim.Szeto@Sun.COM int
61199585STim.Szeto@Sun.COM getProviderData(char *providerName, nvlist_t **nvl, int providerType,
61209585STim.Szeto@Sun.COM     uint64_t *setToken)
61219585STim.Szeto@Sun.COM {
61229585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
61239585STim.Szeto@Sun.COM 	int fd;
61249585STim.Szeto@Sun.COM 	int ioctlRet;
61259585STim.Szeto@Sun.COM 	size_t nvlistSize = ALLOC_PP_DATA_SIZE;
61269585STim.Szeto@Sun.COM 	int retryCnt = 0;
61279585STim.Szeto@Sun.COM 	int retryCntMax = MAX_PROVIDER_RETRY;
61289585STim.Szeto@Sun.COM 	stmf_ppioctl_data_t ppi = {0}, *ppi_out = NULL;
61299585STim.Szeto@Sun.COM 	boolean_t retry = B_TRUE;
61309585STim.Szeto@Sun.COM 	stmf_iocdata_t stmfIoctl;
61319585STim.Szeto@Sun.COM 
61329585STim.Szeto@Sun.COM 	if (providerName == NULL) {
61339585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
61349585STim.Szeto@Sun.COM 	}
61359585STim.Szeto@Sun.COM 
61369585STim.Szeto@Sun.COM 	/*
61379585STim.Szeto@Sun.COM 	 * Open control node for stmf
61389585STim.Szeto@Sun.COM 	 */
61399585STim.Szeto@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
61409585STim.Szeto@Sun.COM 		return (ret);
61419585STim.Szeto@Sun.COM 
61429585STim.Szeto@Sun.COM 	/* set provider name and provider type */
61439585STim.Szeto@Sun.COM 	if (strlcpy(ppi.ppi_name, providerName,
61449585STim.Szeto@Sun.COM 	    sizeof (ppi.ppi_name)) >=
61459585STim.Szeto@Sun.COM 	    sizeof (ppi.ppi_name)) {
61469585STim.Szeto@Sun.COM 		ret = STMF_ERROR_INVALID_ARG;
61479585STim.Szeto@Sun.COM 		goto done;
61489585STim.Szeto@Sun.COM 	}
61499585STim.Szeto@Sun.COM 	switch (providerType) {
61509585STim.Szeto@Sun.COM 		case STMF_LU_PROVIDER_TYPE:
61519585STim.Szeto@Sun.COM 			ppi.ppi_lu_provider = 1;
61529585STim.Szeto@Sun.COM 			break;
61539585STim.Szeto@Sun.COM 		case STMF_PORT_PROVIDER_TYPE:
61549585STim.Szeto@Sun.COM 			ppi.ppi_port_provider = 1;
61559585STim.Szeto@Sun.COM 			break;
61569585STim.Szeto@Sun.COM 		default:
61579585STim.Szeto@Sun.COM 			ret = STMF_ERROR_INVALID_ARG;
61589585STim.Szeto@Sun.COM 			goto done;
61599585STim.Szeto@Sun.COM 	}
61609585STim.Szeto@Sun.COM 
61619585STim.Szeto@Sun.COM 	do {
61629585STim.Szeto@Sun.COM 		/* allocate memory for ioctl */
61639585STim.Szeto@Sun.COM 		ppi_out = (stmf_ppioctl_data_t *)calloc(1, nvlistSize +
61649585STim.Szeto@Sun.COM 		    sizeof (stmf_ppioctl_data_t));
61659585STim.Szeto@Sun.COM 		if (ppi_out == NULL) {
61669585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NOMEM;
61679585STim.Szeto@Sun.COM 			goto done;
61689585STim.Szeto@Sun.COM 
61699585STim.Szeto@Sun.COM 		}
61709585STim.Szeto@Sun.COM 
61719585STim.Szeto@Sun.COM 		/* set the size of the ioctl data to allocated buffer */
61729585STim.Szeto@Sun.COM 		ppi.ppi_data_size = nvlistSize;
61739585STim.Szeto@Sun.COM 
61749585STim.Szeto@Sun.COM 		bzero(&stmfIoctl, sizeof (stmfIoctl));
61759585STim.Szeto@Sun.COM 
61769585STim.Szeto@Sun.COM 		stmfIoctl.stmf_version = STMF_VERSION_1;
61779585STim.Szeto@Sun.COM 		stmfIoctl.stmf_ibuf_size = sizeof (stmf_ppioctl_data_t);
61789585STim.Szeto@Sun.COM 		stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ppi;
61799585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf_size = sizeof (stmf_ppioctl_data_t) +
61809585STim.Szeto@Sun.COM 		    nvlistSize;
61819585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)ppi_out;
61829585STim.Szeto@Sun.COM 		ioctlRet = ioctl(fd, STMF_IOCTL_GET_PP_DATA, &stmfIoctl);
61839585STim.Szeto@Sun.COM 		if (ioctlRet != 0) {
61849585STim.Szeto@Sun.COM 			switch (errno) {
61859585STim.Szeto@Sun.COM 				case EBUSY:
61869585STim.Szeto@Sun.COM 					ret = STMF_ERROR_BUSY;
61879585STim.Szeto@Sun.COM 					break;
61889585STim.Szeto@Sun.COM 				case EPERM:
61899585STim.Szeto@Sun.COM 				case EACCES:
61909585STim.Szeto@Sun.COM 					ret = STMF_ERROR_PERM;
61919585STim.Szeto@Sun.COM 					break;
61929585STim.Szeto@Sun.COM 				case EINVAL:
61939585STim.Szeto@Sun.COM 					if (stmfIoctl.stmf_error ==
61949585STim.Szeto@Sun.COM 					    STMF_IOCERR_INSUFFICIENT_BUF) {
61959585STim.Szeto@Sun.COM 						nvlistSize =
61969585STim.Szeto@Sun.COM 						    ppi_out->ppi_data_size;
61979585STim.Szeto@Sun.COM 						free(ppi_out);
61989585STim.Szeto@Sun.COM 						ppi_out = NULL;
61999585STim.Szeto@Sun.COM 						if (retryCnt++ > retryCntMax) {
62009585STim.Szeto@Sun.COM 							retry = B_FALSE;
62019585STim.Szeto@Sun.COM 							ret = STMF_ERROR_BUSY;
62029585STim.Szeto@Sun.COM 						} else {
62039585STim.Szeto@Sun.COM 							ret =
62049585STim.Szeto@Sun.COM 							    STMF_STATUS_SUCCESS;
62059585STim.Szeto@Sun.COM 						}
62069585STim.Szeto@Sun.COM 					} else {
62079585STim.Szeto@Sun.COM 						syslog(LOG_DEBUG,
62089585STim.Szeto@Sun.COM 						    "getProviderData:ioctl"
62099585STim.Szeto@Sun.COM 						    "unable to retrieve "
62109585STim.Szeto@Sun.COM 						    "nvlist");
62119585STim.Szeto@Sun.COM 						ret = STMF_STATUS_ERROR;
62129585STim.Szeto@Sun.COM 					}
62139585STim.Szeto@Sun.COM 					break;
62149585STim.Szeto@Sun.COM 				case ENOENT:
62159585STim.Szeto@Sun.COM 					ret = STMF_ERROR_NOT_FOUND;
62169585STim.Szeto@Sun.COM 					break;
62179585STim.Szeto@Sun.COM 				default:
62189585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
62199585STim.Szeto@Sun.COM 					    "getProviderData:ioctl errno(%d)",
62209585STim.Szeto@Sun.COM 					    errno);
62219585STim.Szeto@Sun.COM 					ret = STMF_STATUS_ERROR;
62229585STim.Szeto@Sun.COM 					break;
62239585STim.Szeto@Sun.COM 			}
62249585STim.Szeto@Sun.COM 			if (ret != STMF_STATUS_SUCCESS)
62259585STim.Szeto@Sun.COM 				goto done;
62269585STim.Szeto@Sun.COM 		}
62279585STim.Szeto@Sun.COM 	} while (retry && stmfIoctl.stmf_error == STMF_IOCERR_INSUFFICIENT_BUF);
62289585STim.Szeto@Sun.COM 
62299585STim.Szeto@Sun.COM 	if ((ret = nvlist_unpack((char *)ppi_out->ppi_data,
62309585STim.Szeto@Sun.COM 	    ppi_out->ppi_data_size, nvl, 0)) != 0) {
62319585STim.Szeto@Sun.COM 		ret = STMF_STATUS_ERROR;
62329585STim.Szeto@Sun.COM 		goto done;
62339585STim.Szeto@Sun.COM 	}
62349585STim.Szeto@Sun.COM 
62359585STim.Szeto@Sun.COM 	/* caller has asked for new token */
62369585STim.Szeto@Sun.COM 	if (setToken) {
62379585STim.Szeto@Sun.COM 		*setToken = ppi_out->ppi_token;
62389585STim.Szeto@Sun.COM 	}
62399585STim.Szeto@Sun.COM done:
62409585STim.Szeto@Sun.COM 	free(ppi_out);
62419585STim.Szeto@Sun.COM 	(void) close(fd);
62429585STim.Szeto@Sun.COM 	return (ret);
62439585STim.Szeto@Sun.COM }
62449585STim.Szeto@Sun.COM 
62459585STim.Szeto@Sun.COM /*
62467836SJohn.Forte@Sun.COM  * setProviderData
62477836SJohn.Forte@Sun.COM  *
62489585STim.Szeto@Sun.COM  * Purpose: set the provider data in stmf
62497836SJohn.Forte@Sun.COM  *
62507836SJohn.Forte@Sun.COM  * providerName - unique name of provider
62517836SJohn.Forte@Sun.COM  * nvl - nvlist to set
62527836SJohn.Forte@Sun.COM  * providerType - logical unit or port provider
62539585STim.Szeto@Sun.COM  * setToken - stale data token to check if not NULL
62547836SJohn.Forte@Sun.COM  */
62557836SJohn.Forte@Sun.COM static int
62569585STim.Szeto@Sun.COM setProviderData(int fd, char *providerName, nvlist_t *nvl, int providerType,
62579585STim.Szeto@Sun.COM     uint64_t *setToken)
62587836SJohn.Forte@Sun.COM {
62597836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
62607836SJohn.Forte@Sun.COM 	int ioctlRet;
62617836SJohn.Forte@Sun.COM 	size_t nvlistEncodedSize;
62627836SJohn.Forte@Sun.COM 	stmf_ppioctl_data_t *ppi = NULL;
62639585STim.Szeto@Sun.COM 	uint64_t outToken;
62647836SJohn.Forte@Sun.COM 	char *allocatedNvBuffer;
62657836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
62667836SJohn.Forte@Sun.COM 
62677836SJohn.Forte@Sun.COM 	if (providerName == NULL) {
62687836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
62697836SJohn.Forte@Sun.COM 	}
62707836SJohn.Forte@Sun.COM 
62717836SJohn.Forte@Sun.COM 	/* get size of encoded nvlist */
62727836SJohn.Forte@Sun.COM 	if (nvlist_size(nvl, &nvlistEncodedSize, NV_ENCODE_XDR) != 0) {
62737836SJohn.Forte@Sun.COM 		return (STMF_STATUS_ERROR);
62747836SJohn.Forte@Sun.COM 	}
62757836SJohn.Forte@Sun.COM 
62767836SJohn.Forte@Sun.COM 	/* allocate memory for ioctl */
62777836SJohn.Forte@Sun.COM 	ppi = (stmf_ppioctl_data_t *)calloc(1, nvlistEncodedSize +
62787836SJohn.Forte@Sun.COM 	    sizeof (stmf_ppioctl_data_t));
62797836SJohn.Forte@Sun.COM 	if (ppi == NULL) {
62807836SJohn.Forte@Sun.COM 		return (STMF_ERROR_NOMEM);
62817836SJohn.Forte@Sun.COM 	}
62827836SJohn.Forte@Sun.COM 
62839585STim.Szeto@Sun.COM 	if (setToken) {
62849585STim.Szeto@Sun.COM 		ppi->ppi_token_valid = 1;
62859585STim.Szeto@Sun.COM 		ppi->ppi_token = *setToken;
62869585STim.Szeto@Sun.COM 	}
62879585STim.Szeto@Sun.COM 
62887836SJohn.Forte@Sun.COM 	allocatedNvBuffer = (char *)&ppi->ppi_data;
62897836SJohn.Forte@Sun.COM 	if (nvlist_pack(nvl, &allocatedNvBuffer, &nvlistEncodedSize,
62907836SJohn.Forte@Sun.COM 	    NV_ENCODE_XDR, 0) != 0) {
62917836SJohn.Forte@Sun.COM 		return (STMF_STATUS_ERROR);
62927836SJohn.Forte@Sun.COM 	}
62937836SJohn.Forte@Sun.COM 
62947836SJohn.Forte@Sun.COM 	/* set provider name and provider type */
62957836SJohn.Forte@Sun.COM 	(void) strncpy(ppi->ppi_name, providerName, sizeof (ppi->ppi_name));
62967836SJohn.Forte@Sun.COM 	switch (providerType) {
62977836SJohn.Forte@Sun.COM 		case STMF_LU_PROVIDER_TYPE:
62987836SJohn.Forte@Sun.COM 			ppi->ppi_lu_provider = 1;
62997836SJohn.Forte@Sun.COM 			break;
63007836SJohn.Forte@Sun.COM 		case STMF_PORT_PROVIDER_TYPE:
63017836SJohn.Forte@Sun.COM 			ppi->ppi_port_provider = 1;
63027836SJohn.Forte@Sun.COM 			break;
63037836SJohn.Forte@Sun.COM 		default:
63047836SJohn.Forte@Sun.COM 			return (STMF_ERROR_INVALID_ARG);
63057836SJohn.Forte@Sun.COM 	}
63067836SJohn.Forte@Sun.COM 
63077836SJohn.Forte@Sun.COM 	/* set the size of the ioctl data to packed data size */
63087836SJohn.Forte@Sun.COM 	ppi->ppi_data_size = nvlistEncodedSize;
63097836SJohn.Forte@Sun.COM 
63107836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
63117836SJohn.Forte@Sun.COM 
63127836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
63137836SJohn.Forte@Sun.COM 	/*
63147836SJohn.Forte@Sun.COM 	 * Subtracting 8 from the size as that is the size of the last member
63157836SJohn.Forte@Sun.COM 	 * of the structure where the packed data resides
63167836SJohn.Forte@Sun.COM 	 */
63177836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = nvlistEncodedSize +
63187836SJohn.Forte@Sun.COM 	    sizeof (stmf_ppioctl_data_t) - 8;
63197836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)ppi;
63209585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf_size = sizeof (uint64_t);
63219585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&outToken;
63227836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_LOAD_PP_DATA, &stmfIoctl);
63237836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
63247836SJohn.Forte@Sun.COM 		switch (errno) {
63257836SJohn.Forte@Sun.COM 			case EBUSY:
63267836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
63277836SJohn.Forte@Sun.COM 				break;
63289585STim.Szeto@Sun.COM 			case EPERM:
63297836SJohn.Forte@Sun.COM 			case EACCES:
63307836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
63317836SJohn.Forte@Sun.COM 				break;
63329585STim.Szeto@Sun.COM 			case EINVAL:
63339585STim.Szeto@Sun.COM 				if (stmfIoctl.stmf_error ==
63349585STim.Szeto@Sun.COM 				    STMF_IOCERR_PPD_UPDATED) {
63359585STim.Szeto@Sun.COM 					ret = STMF_ERROR_PROV_DATA_STALE;
63369585STim.Szeto@Sun.COM 				} else {
63379585STim.Szeto@Sun.COM 					ret = STMF_STATUS_ERROR;
63389585STim.Szeto@Sun.COM 				}
63399585STim.Szeto@Sun.COM 				break;
63407836SJohn.Forte@Sun.COM 			default:
63417836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
63427836SJohn.Forte@Sun.COM 				    "setProviderData:ioctl errno(%d)", errno);
63437836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
63447836SJohn.Forte@Sun.COM 				break;
63457836SJohn.Forte@Sun.COM 		}
63467836SJohn.Forte@Sun.COM 		if (ret != STMF_STATUS_SUCCESS)
63477836SJohn.Forte@Sun.COM 			goto done;
63487836SJohn.Forte@Sun.COM 	}
63497836SJohn.Forte@Sun.COM 
63509585STim.Szeto@Sun.COM 	/* caller has asked for new token */
63519585STim.Szeto@Sun.COM 	if (setToken) {
63529585STim.Szeto@Sun.COM 		*setToken = outToken;
63539585STim.Szeto@Sun.COM 	}
63547836SJohn.Forte@Sun.COM done:
63557836SJohn.Forte@Sun.COM 	free(ppi);
63567836SJohn.Forte@Sun.COM 	return (ret);
63577836SJohn.Forte@Sun.COM }
63589585STim.Szeto@Sun.COM 
63599585STim.Szeto@Sun.COM /*
63609585STim.Szeto@Sun.COM  * set the persistence method in the library only or library and service
63619585STim.Szeto@Sun.COM  */
63629585STim.Szeto@Sun.COM int
63639585STim.Szeto@Sun.COM stmfSetPersistMethod(uint8_t persistType, boolean_t serviceSet)
63649585STim.Szeto@Sun.COM {
63659585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
63669585STim.Szeto@Sun.COM 	int oldPersist;
63679585STim.Szeto@Sun.COM 
63689585STim.Szeto@Sun.COM 	(void) pthread_mutex_lock(&persistenceTypeLock);
63699585STim.Szeto@Sun.COM 	oldPersist = iPersistType;
63709585STim.Szeto@Sun.COM 	if (persistType == STMF_PERSIST_NONE ||
63719585STim.Szeto@Sun.COM 	    persistType == STMF_PERSIST_SMF) {
63729585STim.Szeto@Sun.COM 		iLibSetPersist = B_TRUE;
63739585STim.Szeto@Sun.COM 		iPersistType = persistType;
63749585STim.Szeto@Sun.COM 	} else {
63759585STim.Szeto@Sun.COM 		(void) pthread_mutex_unlock(&persistenceTypeLock);
63769585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
63779585STim.Szeto@Sun.COM 	}
63789585STim.Szeto@Sun.COM 	/* Is this for this library open or in SMF */
63799585STim.Szeto@Sun.COM 	if (serviceSet == B_TRUE) {
63809585STim.Szeto@Sun.COM 		ret = psSetServicePersist(persistType);
63819585STim.Szeto@Sun.COM 		if (ret != STMF_PS_SUCCESS) {
63829585STim.Szeto@Sun.COM 			ret = STMF_ERROR_PERSIST_TYPE;
63839585STim.Szeto@Sun.COM 			/* Set to old value */
63849585STim.Szeto@Sun.COM 			iPersistType = oldPersist;
63859585STim.Szeto@Sun.COM 		}
63869585STim.Szeto@Sun.COM 	}
63879585STim.Szeto@Sun.COM 	(void) pthread_mutex_unlock(&persistenceTypeLock);
63889585STim.Szeto@Sun.COM 
63899585STim.Szeto@Sun.COM 	return (ret);
63909585STim.Szeto@Sun.COM }
63919585STim.Szeto@Sun.COM 
63929585STim.Szeto@Sun.COM /*
63939585STim.Szeto@Sun.COM  * Only returns internal state for persist. If unset, goes to ps. If that
63949585STim.Szeto@Sun.COM  * fails, returns default setting
63959585STim.Szeto@Sun.COM  */
63969585STim.Szeto@Sun.COM static uint8_t
63979585STim.Szeto@Sun.COM iGetPersistMethod()
63989585STim.Szeto@Sun.COM {
63999585STim.Szeto@Sun.COM 
64009585STim.Szeto@Sun.COM 	uint8_t persistType = 0;
64019585STim.Szeto@Sun.COM 
64029585STim.Szeto@Sun.COM 	(void) pthread_mutex_lock(&persistenceTypeLock);
64039585STim.Szeto@Sun.COM 	if (iLibSetPersist) {
64049585STim.Szeto@Sun.COM 		persistType = iPersistType;
64059585STim.Szeto@Sun.COM 	} else {
64069585STim.Szeto@Sun.COM 		int ret;
64079585STim.Szeto@Sun.COM 		ret = psGetServicePersist(&persistType);
64089585STim.Szeto@Sun.COM 		if (ret != STMF_PS_SUCCESS) {
64099585STim.Szeto@Sun.COM 			/* set to default */
64109585STim.Szeto@Sun.COM 			persistType = STMF_DEFAULT_PERSIST;
64119585STim.Szeto@Sun.COM 		}
64129585STim.Szeto@Sun.COM 	}
64139585STim.Szeto@Sun.COM 	(void) pthread_mutex_unlock(&persistenceTypeLock);
64149585STim.Szeto@Sun.COM 	return (persistType);
64159585STim.Szeto@Sun.COM }
64169585STim.Szeto@Sun.COM 
64179585STim.Szeto@Sun.COM /*
64189585STim.Szeto@Sun.COM  * Returns either library state or persistent config state depending on
64199585STim.Szeto@Sun.COM  * serviceState
64209585STim.Szeto@Sun.COM  */
64219585STim.Szeto@Sun.COM int
64229585STim.Szeto@Sun.COM stmfGetPersistMethod(uint8_t *persistType, boolean_t serviceState)
64239585STim.Szeto@Sun.COM {
64249585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
64259585STim.Szeto@Sun.COM 
64269585STim.Szeto@Sun.COM 	if (persistType == NULL) {
64279585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
64289585STim.Szeto@Sun.COM 	}
64299585STim.Szeto@Sun.COM 	if (serviceState) {
64309585STim.Szeto@Sun.COM 		ret = psGetServicePersist(persistType);
64319585STim.Szeto@Sun.COM 		if (ret != STMF_PS_SUCCESS) {
64329585STim.Szeto@Sun.COM 			ret = STMF_ERROR_PERSIST_TYPE;
64339585STim.Szeto@Sun.COM 		}
64349585STim.Szeto@Sun.COM 	} else {
64359585STim.Szeto@Sun.COM 		(void) pthread_mutex_lock(&persistenceTypeLock);
64369585STim.Szeto@Sun.COM 		if (iLibSetPersist) {
64379585STim.Szeto@Sun.COM 			*persistType = iPersistType;
64389585STim.Szeto@Sun.COM 		} else {
64399585STim.Szeto@Sun.COM 			*persistType = STMF_DEFAULT_PERSIST;
64409585STim.Szeto@Sun.COM 		}
64419585STim.Szeto@Sun.COM 		(void) pthread_mutex_unlock(&persistenceTypeLock);
64429585STim.Szeto@Sun.COM 	}
64439585STim.Szeto@Sun.COM 
64449585STim.Szeto@Sun.COM 	return (ret);
64459585STim.Szeto@Sun.COM }
644610691STim.Szeto@Sun.COM 
644710691STim.Szeto@Sun.COM /*
644810725SJohn.Forte@Sun.COM  * stmfPostProxyMsg
644910725SJohn.Forte@Sun.COM  *
645010725SJohn.Forte@Sun.COM  * Purpose: Post a message to the proxy port provider
645110725SJohn.Forte@Sun.COM  *
645210725SJohn.Forte@Sun.COM  * buf - buffer containing message to post
645310725SJohn.Forte@Sun.COM  * buflen - buffer length
645410725SJohn.Forte@Sun.COM  */
645510725SJohn.Forte@Sun.COM int
645610725SJohn.Forte@Sun.COM stmfPostProxyMsg(int hdl, void *buf, uint32_t buflen)
645710725SJohn.Forte@Sun.COM {
645810725SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
645910725SJohn.Forte@Sun.COM 	int ioctlRet;
646010725SJohn.Forte@Sun.COM 	pppt_iocdata_t ppptIoctl = {0};
646110725SJohn.Forte@Sun.COM 
646210725SJohn.Forte@Sun.COM 	if (buf == NULL) {
646310725SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
646410725SJohn.Forte@Sun.COM 	}
646510725SJohn.Forte@Sun.COM 
646610725SJohn.Forte@Sun.COM 	/*
646710725SJohn.Forte@Sun.COM 	 * Issue ioctl to post the message
646810725SJohn.Forte@Sun.COM 	 */
646910725SJohn.Forte@Sun.COM 	ppptIoctl.pppt_version = PPPT_VERSION_1;
647010725SJohn.Forte@Sun.COM 	ppptIoctl.pppt_buf_size = buflen;
647110725SJohn.Forte@Sun.COM 	ppptIoctl.pppt_buf = (uint64_t)(unsigned long)buf;
647210725SJohn.Forte@Sun.COM 	ioctlRet = ioctl(hdl, PPPT_MESSAGE, &ppptIoctl);
647310725SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
647410725SJohn.Forte@Sun.COM 		switch (errno) {
647510725SJohn.Forte@Sun.COM 			case EPERM:
647610725SJohn.Forte@Sun.COM 			case EACCES:
647710725SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
647810725SJohn.Forte@Sun.COM 				break;
647910725SJohn.Forte@Sun.COM 			default:
648010725SJohn.Forte@Sun.COM 				ret = STMF_ERROR_POST_MSG_FAILED;
648110725SJohn.Forte@Sun.COM 				break;
648210725SJohn.Forte@Sun.COM 		}
648310725SJohn.Forte@Sun.COM 	}
648410725SJohn.Forte@Sun.COM 
648510725SJohn.Forte@Sun.COM 	return (ret);
648610725SJohn.Forte@Sun.COM }
648710725SJohn.Forte@Sun.COM 
648810725SJohn.Forte@Sun.COM /*
648910725SJohn.Forte@Sun.COM  * stmfInitProxyDoor
649010725SJohn.Forte@Sun.COM  *
649110725SJohn.Forte@Sun.COM  * Purpose: Install door in proxy
649210725SJohn.Forte@Sun.COM  *
649310725SJohn.Forte@Sun.COM  * hdl - pointer to returned handle
649410725SJohn.Forte@Sun.COM  * fd - door from door_create()
649510725SJohn.Forte@Sun.COM  */
649610725SJohn.Forte@Sun.COM int
649710725SJohn.Forte@Sun.COM stmfInitProxyDoor(int *hdl, int door)
649810725SJohn.Forte@Sun.COM {
649910725SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
650010725SJohn.Forte@Sun.COM 	int ioctlRet;
650110725SJohn.Forte@Sun.COM 	int fd;
650210725SJohn.Forte@Sun.COM 	pppt_iocdata_t ppptIoctl = {0};
650310725SJohn.Forte@Sun.COM 
650410725SJohn.Forte@Sun.COM 	if (hdl == NULL) {
650510725SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
650610725SJohn.Forte@Sun.COM 	}
650710725SJohn.Forte@Sun.COM 
650810725SJohn.Forte@Sun.COM 	/*
650910725SJohn.Forte@Sun.COM 	 * Open control node for pppt
651010725SJohn.Forte@Sun.COM 	 */
651110725SJohn.Forte@Sun.COM 	if ((ret = openPppt(OPEN_PPPT, &fd)) != STMF_STATUS_SUCCESS) {
651210725SJohn.Forte@Sun.COM 		return (ret);
651310725SJohn.Forte@Sun.COM 	}
651410725SJohn.Forte@Sun.COM 
651510725SJohn.Forte@Sun.COM 	/*
651610725SJohn.Forte@Sun.COM 	 * Issue ioctl to install the door
651710725SJohn.Forte@Sun.COM 	 */
651810725SJohn.Forte@Sun.COM 	ppptIoctl.pppt_version = PPPT_VERSION_1;
651910725SJohn.Forte@Sun.COM 	ppptIoctl.pppt_door_fd = (uint32_t)door;
652010725SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, PPPT_INSTALL_DOOR, &ppptIoctl);
652110725SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
652210725SJohn.Forte@Sun.COM 		switch (errno) {
652310725SJohn.Forte@Sun.COM 			case EPERM:
652410725SJohn.Forte@Sun.COM 			case EACCES:
652510725SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
652610725SJohn.Forte@Sun.COM 				break;
652710725SJohn.Forte@Sun.COM 			case EINVAL:
652810725SJohn.Forte@Sun.COM 				ret = STMF_ERROR_INVALID_ARG;
652910725SJohn.Forte@Sun.COM 				break;
653010725SJohn.Forte@Sun.COM 			case EBUSY:
653110725SJohn.Forte@Sun.COM 				ret = STMF_ERROR_DOOR_INSTALLED;
653210725SJohn.Forte@Sun.COM 				break;
653310725SJohn.Forte@Sun.COM 			default:
653410725SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
653510725SJohn.Forte@Sun.COM 				break;
653610725SJohn.Forte@Sun.COM 		}
653710725SJohn.Forte@Sun.COM 	}
653810725SJohn.Forte@Sun.COM 
653910725SJohn.Forte@Sun.COM 	/* return driver fd to caller */
654010725SJohn.Forte@Sun.COM 	*hdl = fd;
654110725SJohn.Forte@Sun.COM 	return (ret);
654210725SJohn.Forte@Sun.COM }
654310725SJohn.Forte@Sun.COM 
654410725SJohn.Forte@Sun.COM void
654510725SJohn.Forte@Sun.COM stmfDestroyProxyDoor(int hdl)
654610725SJohn.Forte@Sun.COM {
654710725SJohn.Forte@Sun.COM 	(void) close(hdl);
654810725SJohn.Forte@Sun.COM }
654910725SJohn.Forte@Sun.COM 
655010725SJohn.Forte@Sun.COM /*
655110691STim.Szeto@Sun.COM  * validateLunNumIoctl
655210691STim.Szeto@Sun.COM  *
655310691STim.Szeto@Sun.COM  * Purpose: Issues ioctl to check and get available lun# in view entry
655410691STim.Szeto@Sun.COM  *
655510691STim.Szeto@Sun.COM  * viewEntry - view entry to use
655610691STim.Szeto@Sun.COM  */
655710691STim.Szeto@Sun.COM static int
655810691STim.Szeto@Sun.COM validateLunNumIoctl(int fd, stmfViewEntry *viewEntry)
655910691STim.Szeto@Sun.COM {
656010691STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
656110691STim.Szeto@Sun.COM 	int ioctlRet;
656210691STim.Szeto@Sun.COM 	stmf_iocdata_t stmfIoctl;
656310691STim.Szeto@Sun.COM 	stmf_view_op_entry_t ioctlViewEntry;
656410691STim.Szeto@Sun.COM 
656510691STim.Szeto@Sun.COM 	bzero(&ioctlViewEntry, sizeof (ioctlViewEntry));
656610691STim.Szeto@Sun.COM 	/*
656710691STim.Szeto@Sun.COM 	 * don't set ve_ndx or ve_ndx_valid as ve_ndx_valid should be
656810691STim.Szeto@Sun.COM 	 * false on input
656910691STim.Szeto@Sun.COM 	 */
657010691STim.Szeto@Sun.COM 	ioctlViewEntry.ve_lu_number_valid = viewEntry->luNbrValid;
657110691STim.Szeto@Sun.COM 	ioctlViewEntry.ve_all_hosts = viewEntry->allHosts;
657210691STim.Szeto@Sun.COM 	ioctlViewEntry.ve_all_targets = viewEntry->allTargets;
657310691STim.Szeto@Sun.COM 
657410691STim.Szeto@Sun.COM 	if (viewEntry->allHosts == B_FALSE) {
657510691STim.Szeto@Sun.COM 		bcopy(viewEntry->hostGroup, &ioctlViewEntry.ve_host_group.name,
657610691STim.Szeto@Sun.COM 		    sizeof (stmfGroupName));
657710691STim.Szeto@Sun.COM 		ioctlViewEntry.ve_host_group.name_size =
657810691STim.Szeto@Sun.COM 		    strlen((char *)viewEntry->hostGroup);
657910691STim.Szeto@Sun.COM 	}
658010691STim.Szeto@Sun.COM 	if (viewEntry->allTargets == B_FALSE) {
658110691STim.Szeto@Sun.COM 		bcopy(viewEntry->targetGroup,
658210691STim.Szeto@Sun.COM 		    &ioctlViewEntry.ve_target_group.name,
658310691STim.Szeto@Sun.COM 		    sizeof (stmfGroupName));
658410691STim.Szeto@Sun.COM 		ioctlViewEntry.ve_target_group.name_size =
658510691STim.Szeto@Sun.COM 		    strlen((char *)viewEntry->targetGroup);
658610691STim.Szeto@Sun.COM 	}
658710691STim.Szeto@Sun.COM 	/* Validating the lun number */
658810691STim.Szeto@Sun.COM 	if (viewEntry->luNbrValid) {
658910691STim.Szeto@Sun.COM 		bcopy(viewEntry->luNbr, &ioctlViewEntry.ve_lu_nbr,
659010691STim.Szeto@Sun.COM 		    sizeof (ioctlViewEntry.ve_lu_nbr));
659110691STim.Szeto@Sun.COM 	}
659210691STim.Szeto@Sun.COM 
659310691STim.Szeto@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
659410691STim.Szeto@Sun.COM 	/*
659510691STim.Szeto@Sun.COM 	 * Issue ioctl to validate lun# in the view entry
659610691STim.Szeto@Sun.COM 	 */
659710691STim.Szeto@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
659810691STim.Szeto@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry);
659910691STim.Szeto@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry;
660010691STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf_size = sizeof (ioctlViewEntry);
660110691STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&ioctlViewEntry;
660210691STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_VALIDATE_VIEW, &stmfIoctl);
660310691STim.Szeto@Sun.COM 
660410691STim.Szeto@Sun.COM 	/* save available lun number */
660510691STim.Szeto@Sun.COM 	if (!viewEntry->luNbrValid) {
660610691STim.Szeto@Sun.COM 		bcopy(ioctlViewEntry.ve_lu_nbr, viewEntry->luNbr,
660710691STim.Szeto@Sun.COM 		    sizeof (ioctlViewEntry.ve_lu_nbr));
660810691STim.Szeto@Sun.COM 	}
660910691STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
661010691STim.Szeto@Sun.COM 		switch (errno) {
661110691STim.Szeto@Sun.COM 			case EBUSY:
661210691STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
661310691STim.Szeto@Sun.COM 				break;
661410691STim.Szeto@Sun.COM 			case EPERM:
661510691STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
661610691STim.Szeto@Sun.COM 				break;
661710691STim.Szeto@Sun.COM 			case EACCES:
661810691STim.Szeto@Sun.COM 				switch (stmfIoctl.stmf_error) {
661910691STim.Szeto@Sun.COM 					case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
662010691STim.Szeto@Sun.COM 						ret = STMF_ERROR_CONFIG_NONE;
662110691STim.Szeto@Sun.COM 						break;
662210691STim.Szeto@Sun.COM 					default:
662310691STim.Szeto@Sun.COM 						ret = STMF_ERROR_PERM;
662410691STim.Szeto@Sun.COM 						break;
662510691STim.Szeto@Sun.COM 				}
662610691STim.Szeto@Sun.COM 				break;
662710691STim.Szeto@Sun.COM 			default:
662810691STim.Szeto@Sun.COM 				switch (stmfIoctl.stmf_error) {
662910691STim.Szeto@Sun.COM 					case STMF_IOCERR_LU_NUMBER_IN_USE:
663010691STim.Szeto@Sun.COM 						ret = STMF_ERROR_LUN_IN_USE;
663110691STim.Szeto@Sun.COM 						break;
663210691STim.Szeto@Sun.COM 					case STMF_IOCERR_VIEW_ENTRY_CONFLICT:
663310691STim.Szeto@Sun.COM 						ret = STMF_ERROR_VE_CONFLICT;
663410691STim.Szeto@Sun.COM 						break;
663510691STim.Szeto@Sun.COM 					case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
663610691STim.Szeto@Sun.COM 						ret = STMF_ERROR_CONFIG_NONE;
663710691STim.Szeto@Sun.COM 						break;
663810691STim.Szeto@Sun.COM 					case STMF_IOCERR_INVALID_HG:
663910691STim.Szeto@Sun.COM 						ret = STMF_ERROR_INVALID_HG;
664010691STim.Szeto@Sun.COM 						break;
664110691STim.Szeto@Sun.COM 					case STMF_IOCERR_INVALID_TG:
664210691STim.Szeto@Sun.COM 						ret = STMF_ERROR_INVALID_TG;
664310691STim.Szeto@Sun.COM 						break;
664410691STim.Szeto@Sun.COM 					default:
664510691STim.Szeto@Sun.COM 						syslog(LOG_DEBUG,
664610691STim.Szeto@Sun.COM 						    "addViewEntryIoctl"
664710691STim.Szeto@Sun.COM 						    ":error(%d)",
664810691STim.Szeto@Sun.COM 						    stmfIoctl.stmf_error);
664910691STim.Szeto@Sun.COM 						ret = STMF_STATUS_ERROR;
665010691STim.Szeto@Sun.COM 						break;
665110691STim.Szeto@Sun.COM 				}
665210691STim.Szeto@Sun.COM 				break;
665310691STim.Szeto@Sun.COM 		}
665410691STim.Szeto@Sun.COM 	}
665510691STim.Szeto@Sun.COM 	return (ret);
665610691STim.Szeto@Sun.COM }
665710691STim.Szeto@Sun.COM 
665810691STim.Szeto@Sun.COM /*
665910691STim.Szeto@Sun.COM  * stmfValidateView
666010691STim.Szeto@Sun.COM  *
666110691STim.Szeto@Sun.COM  * Purpose: Validate or get lun # base on TG, HG of view entry
666210691STim.Szeto@Sun.COM  *
666310691STim.Szeto@Sun.COM  * viewEntry - view entry structure to use
666410691STim.Szeto@Sun.COM  */
666510691STim.Szeto@Sun.COM int
666610691STim.Szeto@Sun.COM stmfValidateView(stmfViewEntry *viewEntry)
666710691STim.Szeto@Sun.COM {
666810691STim.Szeto@Sun.COM 	int ret;
666910691STim.Szeto@Sun.COM 	int fd;
667010691STim.Szeto@Sun.COM 	stmfViewEntry iViewEntry;
667110691STim.Szeto@Sun.COM 
667210691STim.Szeto@Sun.COM 	if (viewEntry == NULL) {
667310691STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
667410691STim.Szeto@Sun.COM 	}
667510691STim.Szeto@Sun.COM 
667610691STim.Szeto@Sun.COM 	/* initialize and set internal view entry */
667710691STim.Szeto@Sun.COM 	bzero(&iViewEntry, sizeof (iViewEntry));
667810691STim.Szeto@Sun.COM 
667910691STim.Szeto@Sun.COM 	if (!viewEntry->allHosts) {
668010691STim.Szeto@Sun.COM 		bcopy(viewEntry->hostGroup, iViewEntry.hostGroup,
668110691STim.Szeto@Sun.COM 		    sizeof (iViewEntry.hostGroup));
668210691STim.Szeto@Sun.COM 	} else {
668310691STim.Szeto@Sun.COM 		iViewEntry.allHosts = B_TRUE;
668410691STim.Szeto@Sun.COM 	}
668510691STim.Szeto@Sun.COM 
668610691STim.Szeto@Sun.COM 	if (!viewEntry->allTargets) {
668710691STim.Szeto@Sun.COM 		bcopy(viewEntry->targetGroup, iViewEntry.targetGroup,
668810691STim.Szeto@Sun.COM 		    sizeof (iViewEntry.targetGroup));
668910691STim.Szeto@Sun.COM 	} else {
669010691STim.Szeto@Sun.COM 		iViewEntry.allTargets = B_TRUE;
669110691STim.Szeto@Sun.COM 	}
669210691STim.Szeto@Sun.COM 
669310691STim.Szeto@Sun.COM 	if (viewEntry->luNbrValid) {
669410691STim.Szeto@Sun.COM 		iViewEntry.luNbrValid = B_TRUE;
669510691STim.Szeto@Sun.COM 		bcopy(viewEntry->luNbr, iViewEntry.luNbr,
669610691STim.Szeto@Sun.COM 		    sizeof (iViewEntry.luNbr));
669710691STim.Szeto@Sun.COM 	}
669810691STim.Szeto@Sun.COM 
669910691STim.Szeto@Sun.COM 	/*
670010691STim.Szeto@Sun.COM 	 * set users return view entry index valid flag to false
670110691STim.Szeto@Sun.COM 	 * in case of failure
670210691STim.Szeto@Sun.COM 	 */
670310691STim.Szeto@Sun.COM 	viewEntry->veIndexValid = B_FALSE;
670410691STim.Szeto@Sun.COM 
670510691STim.Szeto@Sun.COM 	/* Check to ensure service exists */
670610691STim.Szeto@Sun.COM 	if (psCheckService() != STMF_STATUS_SUCCESS) {
670710691STim.Szeto@Sun.COM 		return (STMF_ERROR_SERVICE_NOT_FOUND);
670810691STim.Szeto@Sun.COM 	}
670910691STim.Szeto@Sun.COM 
671010691STim.Szeto@Sun.COM 	/* call init */
671110691STim.Szeto@Sun.COM 	ret = initializeConfig();
671210691STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
671310691STim.Szeto@Sun.COM 		return (ret);
671410691STim.Szeto@Sun.COM 	}
671510691STim.Szeto@Sun.COM 
671610691STim.Szeto@Sun.COM 	/*
671710691STim.Szeto@Sun.COM 	 * Open control node for stmf
671810691STim.Szeto@Sun.COM 	 */
671910691STim.Szeto@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
672010691STim.Szeto@Sun.COM 		return (ret);
672110691STim.Szeto@Sun.COM 
672210691STim.Szeto@Sun.COM 	/*
672310691STim.Szeto@Sun.COM 	 * Validate lun# in the view entry from the driver
672410691STim.Szeto@Sun.COM 	 */
672510691STim.Szeto@Sun.COM 	ret = validateLunNumIoctl(fd, &iViewEntry);
672610691STim.Szeto@Sun.COM 	(void) close(fd);
672710691STim.Szeto@Sun.COM 
672810691STim.Szeto@Sun.COM 	/* save available lun number */
672910691STim.Szeto@Sun.COM 	if (!viewEntry->luNbrValid) {
673010691STim.Szeto@Sun.COM 		bcopy(iViewEntry.luNbr, viewEntry->luNbr,
673110691STim.Szeto@Sun.COM 		    sizeof (iViewEntry.luNbr));
673210691STim.Szeto@Sun.COM 	}
673310691STim.Szeto@Sun.COM 
673410691STim.Szeto@Sun.COM 	return (ret);
673510691STim.Szeto@Sun.COM }
6736