17836SJohn.Forte@Sun.COM /*
27836SJohn.Forte@Sun.COM  * CDDL HEADER START
37836SJohn.Forte@Sun.COM  *
47836SJohn.Forte@Sun.COM  * The contents of this file are subject to the terms of the
57836SJohn.Forte@Sun.COM  * Common Development and Distribution License (the "License").
67836SJohn.Forte@Sun.COM  * You may not use this file except in compliance with the License.
77836SJohn.Forte@Sun.COM  *
87836SJohn.Forte@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97836SJohn.Forte@Sun.COM  * or http://www.opensolaris.org/os/licensing.
107836SJohn.Forte@Sun.COM  * See the License for the specific language governing permissions
117836SJohn.Forte@Sun.COM  * and limitations under the License.
127836SJohn.Forte@Sun.COM  *
137836SJohn.Forte@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
147836SJohn.Forte@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157836SJohn.Forte@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
167836SJohn.Forte@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
177836SJohn.Forte@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
187836SJohn.Forte@Sun.COM  *
197836SJohn.Forte@Sun.COM  * CDDL HEADER END
207836SJohn.Forte@Sun.COM  */
217836SJohn.Forte@Sun.COM /*
22*9585STim.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>
46*9585STim.Szeto@Sun.COM #include <math.h>
47*9585STim.Szeto@Sun.COM #include <libstmf_impl.h>
487836SJohn.Forte@Sun.COM #include <sys/stmf_ioctl.h>
49*9585STim.Szeto@Sun.COM #include <sys/stmf_sbd_ioctl.h>
507836SJohn.Forte@Sun.COM 
517836SJohn.Forte@Sun.COM #define	STMF_PATH    "/devices/pseudo/stmf@0:admin"
52*9585STim.Szeto@Sun.COM #define	SBD_PATH    "/devices/pseudo/stmf_sbd@0:admin"
537836SJohn.Forte@Sun.COM 
547836SJohn.Forte@Sun.COM #define	EUI "eui."
557836SJohn.Forte@Sun.COM #define	WWN "wwn."
567836SJohn.Forte@Sun.COM #define	IQN "iqn."
57*9585STim.Szeto@Sun.COM #define	LU_ASCII_GUID_SIZE 32
58*9585STim.Szeto@Sun.COM #define	LU_GUID_SIZE 16
59*9585STim.Szeto@Sun.COM #define	OUI_ASCII_SIZE 6
60*9585STim.Szeto@Sun.COM #define	OUI_SIZE 3
617836SJohn.Forte@Sun.COM #define	IDENT_LENGTH_BYTE 3
627836SJohn.Forte@Sun.COM 
63*9585STim.Szeto@Sun.COM /* various initial allocation values */
64*9585STim.Szeto@Sun.COM #define	ALLOC_LU		8192
65*9585STim.Szeto@Sun.COM #define	ALLOC_TARGET_PORT	2048
66*9585STim.Szeto@Sun.COM #define	ALLOC_PROVIDER		64
67*9585STim.Szeto@Sun.COM #define	ALLOC_GROUP		2048
68*9585STim.Szeto@Sun.COM #define	ALLOC_SESSION		2048
69*9585STim.Szeto@Sun.COM #define	ALLOC_VE		256
70*9585STim.Szeto@Sun.COM #define	ALLOC_PP_DATA_SIZE	128*1024
71*9585STim.Szeto@Sun.COM #define	ALLOC_GRP_MEMBER	256
72*9585STim.Szeto@Sun.COM 
737836SJohn.Forte@Sun.COM #define	MAX_ISCSI_NAME	223
74*9585STim.Szeto@Sun.COM #define	MAX_SERIAL_SIZE 252 + 1
75*9585STim.Szeto@Sun.COM #define	MAX_LU_ALIAS_SIZE 256
76*9585STim.Szeto@Sun.COM #define	MAX_SBD_PROPS	MAXPATHLEN + MAX_SERIAL_SIZE + MAX_LU_ALIAS_SIZE
777836SJohn.Forte@Sun.COM 
787836SJohn.Forte@Sun.COM #define	OPEN_STMF 0
797836SJohn.Forte@Sun.COM #define	OPEN_EXCL_STMF O_EXCL
807836SJohn.Forte@Sun.COM 
81*9585STim.Szeto@Sun.COM #define	OPEN_SBD 0
82*9585STim.Szeto@Sun.COM #define	OPEN_EXCL_SBD O_EXCL
83*9585STim.Szeto@Sun.COM 
847836SJohn.Forte@Sun.COM #define	LOGICAL_UNIT_TYPE 0
857836SJohn.Forte@Sun.COM #define	TARGET_TYPE 1
867836SJohn.Forte@Sun.COM #define	STMF_SERVICE_TYPE 2
877836SJohn.Forte@Sun.COM 
88*9585STim.Szeto@Sun.COM #define	HOST_GROUP   1
89*9585STim.Szeto@Sun.COM #define	TARGET_GROUP 2
90*9585STim.Szeto@Sun.COM 
91*9585STim.Szeto@Sun.COM /* set default persistence here */
92*9585STim.Szeto@Sun.COM #define	STMF_DEFAULT_PERSIST	STMF_PERSIST_SMF
93*9585STim.Szeto@Sun.COM 
94*9585STim.Szeto@Sun.COM #define	MAX_PROVIDER_RETRY 30
95*9585STim.Szeto@Sun.COM 
967836SJohn.Forte@Sun.COM static int openStmf(int, int *fd);
97*9585STim.Szeto@Sun.COM static int openSbd(int, int *fd);
987836SJohn.Forte@Sun.COM static int groupIoctl(int fd, int cmd, stmfGroupName *);
997836SJohn.Forte@Sun.COM static int loadStore(int fd);
1007836SJohn.Forte@Sun.COM static int initializeConfig();
1017836SJohn.Forte@Sun.COM static int groupMemberIoctl(int fd, int cmd, stmfGroupName *, stmfDevid *);
1027836SJohn.Forte@Sun.COM static int guidCompare(const void *, const void *);
1037836SJohn.Forte@Sun.COM static int addViewEntryIoctl(int fd, stmfGuid *, stmfViewEntry *);
1047836SJohn.Forte@Sun.COM static int loadHostGroups(int fd, stmfGroupList *);
1057836SJohn.Forte@Sun.COM static int loadTargetGroups(int fd, stmfGroupList *);
1067836SJohn.Forte@Sun.COM static int getStmfState(stmf_state_desc_t *);
1077836SJohn.Forte@Sun.COM static int setStmfState(int fd, stmf_state_desc_t *, int);
108*9585STim.Szeto@Sun.COM static int setProviderData(int fd, char *, nvlist_t *, int, uint64_t *);
109*9585STim.Szeto@Sun.COM static int createDiskResource(luResourceImpl *);
110*9585STim.Szeto@Sun.COM static int createDiskLu(diskResource *, stmfGuid *);
111*9585STim.Szeto@Sun.COM static int deleteDiskLu(stmfGuid *luGuid);
112*9585STim.Szeto@Sun.COM static int getDiskProp(luResourceImpl *, uint32_t, char *, size_t *);
113*9585STim.Szeto@Sun.COM static int getDiskAllProps(stmfGuid *luGuid, luResource *hdl);
114*9585STim.Szeto@Sun.COM static int loadDiskPropsFromDriver(luResourceImpl *, sbd_lu_props_t *);
115*9585STim.Szeto@Sun.COM static int removeGuidFromDiskStore(stmfGuid *);
116*9585STim.Szeto@Sun.COM static int addGuidToDiskStore(stmfGuid *, char *);
117*9585STim.Szeto@Sun.COM static int persistDiskGuid(stmfGuid *, char *, boolean_t);
118*9585STim.Szeto@Sun.COM static int setDiskProp(luResourceImpl *, uint32_t, const char *);
119*9585STim.Szeto@Sun.COM static int checkHexUpper(char *);
120*9585STim.Szeto@Sun.COM static int strToShift(const char *);
121*9585STim.Szeto@Sun.COM static int niceStrToNum(const char *, uint64_t *);
122*9585STim.Szeto@Sun.COM static void diskError(uint32_t, int *);
123*9585STim.Szeto@Sun.COM static int importDiskLu(char *fname, stmfGuid *);
124*9585STim.Szeto@Sun.COM static int modifyDiskLu(diskResource *, stmfGuid *, const char *);
125*9585STim.Szeto@Sun.COM static int modifyDiskLuProp(stmfGuid *, const char *, uint32_t, const char *);
126*9585STim.Szeto@Sun.COM static int validateModifyDiskProp(uint32_t);
127*9585STim.Szeto@Sun.COM static uint8_t iGetPersistMethod();
128*9585STim.Szeto@Sun.COM static int groupListIoctl(stmfGroupList **, int);
129*9585STim.Szeto@Sun.COM static int iLoadGroupFromPs(stmfGroupList **, int);
130*9585STim.Szeto@Sun.COM static int groupMemberListIoctl(stmfGroupName *, stmfGroupProperties **, int);
131*9585STim.Szeto@Sun.COM static int getProviderData(char *, nvlist_t **, int, uint64_t *);
132*9585STim.Szeto@Sun.COM static int viewEntryCompare(const void *, const void *);
133*9585STim.Szeto@Sun.COM 
134*9585STim.Szeto@Sun.COM static pthread_mutex_t persistenceTypeLock = PTHREAD_MUTEX_INITIALIZER;
135*9585STim.Szeto@Sun.COM static int iPersistType = 0;
136*9585STim.Szeto@Sun.COM /* when B_TRUE, no need to access SMF anymore. Just use iPersistType */
137*9585STim.Szeto@Sun.COM static boolean_t iLibSetPersist = B_FALSE;
1387836SJohn.Forte@Sun.COM 
1397836SJohn.Forte@Sun.COM /*
1407836SJohn.Forte@Sun.COM  * Open for stmf module
1417836SJohn.Forte@Sun.COM  *
1427836SJohn.Forte@Sun.COM  * flag - open flag (OPEN_STMF, OPEN_EXCL_STMF)
1437836SJohn.Forte@Sun.COM  * fd - pointer to integer. On success, contains the stmf file descriptor
1447836SJohn.Forte@Sun.COM  */
1457836SJohn.Forte@Sun.COM static int
1467836SJohn.Forte@Sun.COM openStmf(int flag, int *fd)
1477836SJohn.Forte@Sun.COM {
1487836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_ERROR;
1497836SJohn.Forte@Sun.COM 
1507836SJohn.Forte@Sun.COM 	if ((*fd = open(STMF_PATH, O_NDELAY | O_RDONLY | flag)) != -1) {
1517836SJohn.Forte@Sun.COM 		ret = STMF_STATUS_SUCCESS;
1527836SJohn.Forte@Sun.COM 	} else {
1537836SJohn.Forte@Sun.COM 		if (errno == EBUSY) {
1547836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
155*9585STim.Szeto@Sun.COM 		} else if (errno == EACCES) {
156*9585STim.Szeto@Sun.COM 			ret = STMF_ERROR_PERM;
1577836SJohn.Forte@Sun.COM 		} else {
1587836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
1597836SJohn.Forte@Sun.COM 		}
1607836SJohn.Forte@Sun.COM 		syslog(LOG_DEBUG, "openStmf:open failure:%s:errno(%d)",
1617836SJohn.Forte@Sun.COM 		    STMF_PATH, errno);
1627836SJohn.Forte@Sun.COM 	}
1637836SJohn.Forte@Sun.COM 
1647836SJohn.Forte@Sun.COM 	return (ret);
1657836SJohn.Forte@Sun.COM }
1667836SJohn.Forte@Sun.COM 
1677836SJohn.Forte@Sun.COM /*
168*9585STim.Szeto@Sun.COM  * Open for sbd module
169*9585STim.Szeto@Sun.COM  *
170*9585STim.Szeto@Sun.COM  * flag - open flag (OPEN_STMF, OPEN_EXCL_STMF)
171*9585STim.Szeto@Sun.COM  * fd - pointer to integer. On success, contains the stmf file descriptor
172*9585STim.Szeto@Sun.COM  */
173*9585STim.Szeto@Sun.COM static int
174*9585STim.Szeto@Sun.COM openSbd(int flag, int *fd)
175*9585STim.Szeto@Sun.COM {
176*9585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_ERROR;
177*9585STim.Szeto@Sun.COM 
178*9585STim.Szeto@Sun.COM 	if ((*fd = open(SBD_PATH, O_NDELAY | O_RDONLY | flag)) != -1) {
179*9585STim.Szeto@Sun.COM 		ret = STMF_STATUS_SUCCESS;
180*9585STim.Szeto@Sun.COM 	} else {
181*9585STim.Szeto@Sun.COM 		if (errno == EBUSY) {
182*9585STim.Szeto@Sun.COM 			ret = STMF_ERROR_BUSY;
183*9585STim.Szeto@Sun.COM 		} else if (errno == EACCES) {
184*9585STim.Szeto@Sun.COM 			ret = STMF_ERROR_PERM;
185*9585STim.Szeto@Sun.COM 		} else {
186*9585STim.Szeto@Sun.COM 			ret = STMF_STATUS_ERROR;
187*9585STim.Szeto@Sun.COM 		}
188*9585STim.Szeto@Sun.COM 		syslog(LOG_DEBUG, "openSbd:open failure:%s:errno(%d)",
189*9585STim.Szeto@Sun.COM 		    SBD_PATH, errno);
190*9585STim.Szeto@Sun.COM 	}
191*9585STim.Szeto@Sun.COM 
192*9585STim.Szeto@Sun.COM 	return (ret);
193*9585STim.Szeto@Sun.COM }
194*9585STim.Szeto@Sun.COM 
195*9585STim.Szeto@Sun.COM /*
1967836SJohn.Forte@Sun.COM  * initializeConfig
1977836SJohn.Forte@Sun.COM  *
1987836SJohn.Forte@Sun.COM  * This routine should be called before any ioctl requiring initialization
1997836SJohn.Forte@Sun.COM  * which is basically everything except stmfGetState(), setStmfState() and
2007836SJohn.Forte@Sun.COM  * stmfLoadConfig().
2017836SJohn.Forte@Sun.COM  */
2027836SJohn.Forte@Sun.COM static int
2037836SJohn.Forte@Sun.COM initializeConfig()
2047836SJohn.Forte@Sun.COM {
2057836SJohn.Forte@Sun.COM 	int ret;
2067836SJohn.Forte@Sun.COM 	stmfState state;
2077836SJohn.Forte@Sun.COM 
2087836SJohn.Forte@Sun.COM 
2097836SJohn.Forte@Sun.COM 	ret = stmfGetState(&state);
2107836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
2117836SJohn.Forte@Sun.COM 		return (ret);
2127836SJohn.Forte@Sun.COM 	}
2137836SJohn.Forte@Sun.COM 
2147836SJohn.Forte@Sun.COM 	/* if we've already initialized or in the process, return success */
2157836SJohn.Forte@Sun.COM 	if (state.configState == STMF_CONFIG_STATE_INIT_DONE ||
2167836SJohn.Forte@Sun.COM 	    state.configState == STMF_CONFIG_STATE_INIT) {
2177836SJohn.Forte@Sun.COM 		return (STMF_STATUS_SUCCESS);
2187836SJohn.Forte@Sun.COM 	}
2197836SJohn.Forte@Sun.COM 
2207836SJohn.Forte@Sun.COM 	ret = stmfLoadConfig();
2217836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
2227836SJohn.Forte@Sun.COM 		syslog(LOG_DEBUG,
2237836SJohn.Forte@Sun.COM 		    "initializeConfig:stmfLoadConfig:error(%d)", ret);
2247836SJohn.Forte@Sun.COM 		return (ret);
2257836SJohn.Forte@Sun.COM 	}
2267836SJohn.Forte@Sun.COM 
2277836SJohn.Forte@Sun.COM 	ret = stmfGetState(&state);
2287836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
2297836SJohn.Forte@Sun.COM 		syslog(LOG_DEBUG,
2307836SJohn.Forte@Sun.COM 		    "initializeConfig:stmfGetState:error(%d)", ret);
2317836SJohn.Forte@Sun.COM 		return (ret);
2327836SJohn.Forte@Sun.COM 	}
2337836SJohn.Forte@Sun.COM 
2347836SJohn.Forte@Sun.COM 	if (state.configState != STMF_CONFIG_STATE_INIT_DONE) {
2357836SJohn.Forte@Sun.COM 		syslog(LOG_DEBUG, "initializeConfig:state.configState(%d)",
2367836SJohn.Forte@Sun.COM 		    state.configState);
2377836SJohn.Forte@Sun.COM 		ret = STMF_STATUS_ERROR;
2387836SJohn.Forte@Sun.COM 	}
2397836SJohn.Forte@Sun.COM 
2407836SJohn.Forte@Sun.COM 	return (ret);
2417836SJohn.Forte@Sun.COM }
2427836SJohn.Forte@Sun.COM 
2437836SJohn.Forte@Sun.COM 
2447836SJohn.Forte@Sun.COM /*
2457836SJohn.Forte@Sun.COM  * groupIoctl
2467836SJohn.Forte@Sun.COM  *
2477836SJohn.Forte@Sun.COM  * Purpose: issue ioctl for create/delete on group
2487836SJohn.Forte@Sun.COM  *
2497836SJohn.Forte@Sun.COM  * cmd - valid STMF ioctl group cmd
2507836SJohn.Forte@Sun.COM  * groupName - groupName to create or delete
2517836SJohn.Forte@Sun.COM  */
2527836SJohn.Forte@Sun.COM static int
2537836SJohn.Forte@Sun.COM groupIoctl(int fd, int cmd, stmfGroupName *groupName)
2547836SJohn.Forte@Sun.COM {
2557836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
2567836SJohn.Forte@Sun.COM 	int ioctlRet;
2577836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
2587836SJohn.Forte@Sun.COM 	stmf_group_name_t iGroupName;
2597836SJohn.Forte@Sun.COM 
2607836SJohn.Forte@Sun.COM 	bzero(&iGroupName, sizeof (iGroupName));
2617836SJohn.Forte@Sun.COM 
2627836SJohn.Forte@Sun.COM 	bcopy(groupName, &iGroupName.name, strlen((char *)groupName));
2637836SJohn.Forte@Sun.COM 
2647836SJohn.Forte@Sun.COM 	iGroupName.name_size = strlen((char *)groupName);
2657836SJohn.Forte@Sun.COM 
2667836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
2677836SJohn.Forte@Sun.COM 	/*
2687836SJohn.Forte@Sun.COM 	 * Issue ioctl to create the host group
2697836SJohn.Forte@Sun.COM 	 */
2707836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
2717836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (iGroupName);
2727836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&iGroupName;
2737836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
2747836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
2757836SJohn.Forte@Sun.COM 		switch (errno) {
276*9585STim.Szeto@Sun.COM 			case EPERM:
2777836SJohn.Forte@Sun.COM 			case EACCES:
2787836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
2797836SJohn.Forte@Sun.COM 				break;
2807836SJohn.Forte@Sun.COM 			default:
2817836SJohn.Forte@Sun.COM 				switch (stmfIoctl.stmf_error) {
2827836SJohn.Forte@Sun.COM 					case STMF_IOCERR_TG_EXISTS:
2837836SJohn.Forte@Sun.COM 					case STMF_IOCERR_HG_EXISTS:
2847836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_EXISTS;
2857836SJohn.Forte@Sun.COM 						break;
2867836SJohn.Forte@Sun.COM 					case STMF_IOCERR_TG_IN_USE:
2877836SJohn.Forte@Sun.COM 					case STMF_IOCERR_HG_IN_USE:
2887836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_GROUP_IN_USE;
2897836SJohn.Forte@Sun.COM 						break;
2907836SJohn.Forte@Sun.COM 					case STMF_IOCERR_INVALID_HG:
2917836SJohn.Forte@Sun.COM 					case STMF_IOCERR_INVALID_TG:
2927836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_NOT_FOUND;
2937836SJohn.Forte@Sun.COM 						break;
2947836SJohn.Forte@Sun.COM 					default:
2957836SJohn.Forte@Sun.COM 						syslog(LOG_DEBUG,
2967836SJohn.Forte@Sun.COM 						    "groupIoctl:error(%d)",
2977836SJohn.Forte@Sun.COM 						    stmfIoctl.stmf_error);
2987836SJohn.Forte@Sun.COM 						ret = STMF_STATUS_ERROR;
2997836SJohn.Forte@Sun.COM 						break;
3007836SJohn.Forte@Sun.COM 				}
3017836SJohn.Forte@Sun.COM 				break;
3027836SJohn.Forte@Sun.COM 		}
3037836SJohn.Forte@Sun.COM 	}
3047836SJohn.Forte@Sun.COM done:
3057836SJohn.Forte@Sun.COM 	return (ret);
3067836SJohn.Forte@Sun.COM }
3077836SJohn.Forte@Sun.COM 
3087836SJohn.Forte@Sun.COM /*
309*9585STim.Szeto@Sun.COM  * groupMemberIoctl
3107836SJohn.Forte@Sun.COM  *
3117836SJohn.Forte@Sun.COM  * Purpose: issue ioctl for add/remove member on group
3127836SJohn.Forte@Sun.COM  *
3137836SJohn.Forte@Sun.COM  * cmd - valid STMF ioctl group member cmd
3147836SJohn.Forte@Sun.COM  * groupName - groupName to add to or remove from
3157836SJohn.Forte@Sun.COM  * devid - group member to add or remove
3167836SJohn.Forte@Sun.COM  */
3177836SJohn.Forte@Sun.COM static int
3187836SJohn.Forte@Sun.COM groupMemberIoctl(int fd, int cmd, stmfGroupName *groupName, stmfDevid *devid)
3197836SJohn.Forte@Sun.COM {
3207836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
3217836SJohn.Forte@Sun.COM 	int ioctlRet;
3227836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
3237836SJohn.Forte@Sun.COM 	stmf_group_op_data_t stmfGroupData;
3247836SJohn.Forte@Sun.COM 
3257836SJohn.Forte@Sun.COM 	bzero(&stmfGroupData, sizeof (stmfGroupData));
3267836SJohn.Forte@Sun.COM 
3277836SJohn.Forte@Sun.COM 	bcopy(groupName, &stmfGroupData.group.name, strlen((char *)groupName));
3287836SJohn.Forte@Sun.COM 
3297836SJohn.Forte@Sun.COM 	stmfGroupData.group.name_size = strlen((char *)groupName);
3307836SJohn.Forte@Sun.COM 	stmfGroupData.ident[IDENT_LENGTH_BYTE] = devid->identLength;
3317836SJohn.Forte@Sun.COM 	bcopy(&(devid->ident), &stmfGroupData.ident[IDENT_LENGTH_BYTE + 1],
3327836SJohn.Forte@Sun.COM 	    devid->identLength);
3337836SJohn.Forte@Sun.COM 
3347836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
3357836SJohn.Forte@Sun.COM 	/*
3367836SJohn.Forte@Sun.COM 	 * Issue ioctl to add to the host group
3377836SJohn.Forte@Sun.COM 	 */
3387836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
3397836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (stmfGroupData);
3407836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&stmfGroupData;
3417836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
3427836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
3437836SJohn.Forte@Sun.COM 		switch (errno) {
3447836SJohn.Forte@Sun.COM 			case EBUSY:
3457836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
3467836SJohn.Forte@Sun.COM 				break;
347*9585STim.Szeto@Sun.COM 			case EPERM:
3487836SJohn.Forte@Sun.COM 			case EACCES:
3497836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
3507836SJohn.Forte@Sun.COM 				break;
3517836SJohn.Forte@Sun.COM 			default:
3527836SJohn.Forte@Sun.COM 				switch (stmfIoctl.stmf_error) {
3537836SJohn.Forte@Sun.COM 					case STMF_IOCERR_TG_ENTRY_EXISTS:
3547836SJohn.Forte@Sun.COM 					case STMF_IOCERR_HG_ENTRY_EXISTS:
3557836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_EXISTS;
3567836SJohn.Forte@Sun.COM 						break;
3577836SJohn.Forte@Sun.COM 					case STMF_IOCERR_INVALID_TG_ENTRY:
3587836SJohn.Forte@Sun.COM 					case STMF_IOCERR_INVALID_HG_ENTRY:
3597836SJohn.Forte@Sun.COM 						ret =
3607836SJohn.Forte@Sun.COM 						    STMF_ERROR_MEMBER_NOT_FOUND;
3617836SJohn.Forte@Sun.COM 						break;
3627836SJohn.Forte@Sun.COM 					case STMF_IOCERR_INVALID_TG:
3637836SJohn.Forte@Sun.COM 					case STMF_IOCERR_INVALID_HG:
3647836SJohn.Forte@Sun.COM 						ret =
3657836SJohn.Forte@Sun.COM 						    STMF_ERROR_GROUP_NOT_FOUND;
3667836SJohn.Forte@Sun.COM 						break;
3677836SJohn.Forte@Sun.COM 					default:
3687836SJohn.Forte@Sun.COM 						syslog(LOG_DEBUG,
3697836SJohn.Forte@Sun.COM 						    "groupMemberIoctl:error"
3707836SJohn.Forte@Sun.COM 						    "(%d)",
3717836SJohn.Forte@Sun.COM 						    stmfIoctl.stmf_error);
3727836SJohn.Forte@Sun.COM 						ret = STMF_STATUS_ERROR;
3737836SJohn.Forte@Sun.COM 						break;
3747836SJohn.Forte@Sun.COM 				}
3757836SJohn.Forte@Sun.COM 				break;
3767836SJohn.Forte@Sun.COM 		}
3777836SJohn.Forte@Sun.COM 	}
3787836SJohn.Forte@Sun.COM done:
3797836SJohn.Forte@Sun.COM 	return (ret);
3807836SJohn.Forte@Sun.COM }
3817836SJohn.Forte@Sun.COM 
3827836SJohn.Forte@Sun.COM /*
383*9585STim.Szeto@Sun.COM  * qsort function
384*9585STim.Szeto@Sun.COM  * sort on veIndex
385*9585STim.Szeto@Sun.COM  */
386*9585STim.Szeto@Sun.COM static int
387*9585STim.Szeto@Sun.COM viewEntryCompare(const void *p1, const void *p2)
388*9585STim.Szeto@Sun.COM {
389*9585STim.Szeto@Sun.COM 
390*9585STim.Szeto@Sun.COM 	stmfViewEntry *v1 = (stmfViewEntry *)p1, *v2 = (stmfViewEntry *)p2;
391*9585STim.Szeto@Sun.COM 	if (v1->veIndex > v2->veIndex)
392*9585STim.Szeto@Sun.COM 		return (1);
393*9585STim.Szeto@Sun.COM 	if (v1->veIndex < v2->veIndex)
394*9585STim.Szeto@Sun.COM 		return (-1);
395*9585STim.Szeto@Sun.COM 	return (0);
396*9585STim.Szeto@Sun.COM }
397*9585STim.Szeto@Sun.COM 
398*9585STim.Szeto@Sun.COM /*
3997836SJohn.Forte@Sun.COM  * guidCompare
4007836SJohn.Forte@Sun.COM  *
4017836SJohn.Forte@Sun.COM  * qsort function
4027836SJohn.Forte@Sun.COM  * sort on guid
4037836SJohn.Forte@Sun.COM  */
4047836SJohn.Forte@Sun.COM static int
4057836SJohn.Forte@Sun.COM guidCompare(const void *p1, const void *p2)
4067836SJohn.Forte@Sun.COM {
4077836SJohn.Forte@Sun.COM 
4087836SJohn.Forte@Sun.COM 	stmfGuid *g1 = (stmfGuid *)p1, *g2 = (stmfGuid *)p2;
4097836SJohn.Forte@Sun.COM 	int i;
4107836SJohn.Forte@Sun.COM 
4117836SJohn.Forte@Sun.COM 	for (i = 0; i < sizeof (stmfGuid); i++) {
4127836SJohn.Forte@Sun.COM 		if (g1->guid[i] > g2->guid[i])
4137836SJohn.Forte@Sun.COM 			return (1);
4147836SJohn.Forte@Sun.COM 		if (g1->guid[i] < g2->guid[i])
4157836SJohn.Forte@Sun.COM 			return (-1);
4167836SJohn.Forte@Sun.COM 	}
4177836SJohn.Forte@Sun.COM 
4187836SJohn.Forte@Sun.COM 	return (0);
4197836SJohn.Forte@Sun.COM }
4207836SJohn.Forte@Sun.COM 
4217836SJohn.Forte@Sun.COM /*
4227836SJohn.Forte@Sun.COM  * stmfAddToHostGroup
4237836SJohn.Forte@Sun.COM  *
4247836SJohn.Forte@Sun.COM  * Purpose: Adds an initiator to an existing host group
4257836SJohn.Forte@Sun.COM  *
4267836SJohn.Forte@Sun.COM  * hostGroupName - name of an existing host group
4277836SJohn.Forte@Sun.COM  * hostName - name of initiator to add
4287836SJohn.Forte@Sun.COM  */
4297836SJohn.Forte@Sun.COM int
4307836SJohn.Forte@Sun.COM stmfAddToHostGroup(stmfGroupName *hostGroupName, stmfDevid *hostName)
4317836SJohn.Forte@Sun.COM {
4327836SJohn.Forte@Sun.COM 	int ret;
4337836SJohn.Forte@Sun.COM 	int fd;
4347836SJohn.Forte@Sun.COM 
4357836SJohn.Forte@Sun.COM 	if (hostGroupName == NULL ||
4367836SJohn.Forte@Sun.COM 	    (strnlen((char *)hostGroupName, sizeof (stmfGroupName))
4377836SJohn.Forte@Sun.COM 	    == sizeof (stmfGroupName)) || hostName == NULL) {
4387836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
4397836SJohn.Forte@Sun.COM 	}
4407836SJohn.Forte@Sun.COM 
4417836SJohn.Forte@Sun.COM 	/* call init */
4427836SJohn.Forte@Sun.COM 	ret = initializeConfig();
4437836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
4447836SJohn.Forte@Sun.COM 		return (ret);
4457836SJohn.Forte@Sun.COM 	}
4467836SJohn.Forte@Sun.COM 
4477836SJohn.Forte@Sun.COM 	/*
4487836SJohn.Forte@Sun.COM 	 * Open control node for stmf
4497836SJohn.Forte@Sun.COM 	 */
4507836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
4517836SJohn.Forte@Sun.COM 		return (ret);
4527836SJohn.Forte@Sun.COM 
4537836SJohn.Forte@Sun.COM 	if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_HG_ENTRY, hostGroupName,
4547836SJohn.Forte@Sun.COM 	    hostName)) != STMF_STATUS_SUCCESS) {
4557836SJohn.Forte@Sun.COM 		goto done;
4567836SJohn.Forte@Sun.COM 	}
4577836SJohn.Forte@Sun.COM 
458*9585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
459*9585STim.Szeto@Sun.COM 		goto done;
460*9585STim.Szeto@Sun.COM 	}
461*9585STim.Szeto@Sun.COM 
4627836SJohn.Forte@Sun.COM 	ret = psAddHostGroupMember((char *)hostGroupName,
4637836SJohn.Forte@Sun.COM 	    (char *)hostName->ident);
4647836SJohn.Forte@Sun.COM 	switch (ret) {
4657836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
4667836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
4677836SJohn.Forte@Sun.COM 			break;
4687836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_EXISTS:
4697836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_EXISTS;
4707836SJohn.Forte@Sun.COM 			break;
4717836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_GROUP_NOT_FOUND:
4727836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_GROUP_NOT_FOUND;
4737836SJohn.Forte@Sun.COM 			break;
4747836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
4757836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
4767836SJohn.Forte@Sun.COM 			break;
4777836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
4787836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
4797836SJohn.Forte@Sun.COM 			break;
4807836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
4817836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
4827836SJohn.Forte@Sun.COM 			break;
4837836SJohn.Forte@Sun.COM 		default:
4847836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
4857836SJohn.Forte@Sun.COM 			    "stmfAddToHostGroup:psAddHostGroupMember:error(%d)",
4867836SJohn.Forte@Sun.COM 			    ret);
4877836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
4887836SJohn.Forte@Sun.COM 			break;
4897836SJohn.Forte@Sun.COM 	}
4907836SJohn.Forte@Sun.COM 
4917836SJohn.Forte@Sun.COM done:
4927836SJohn.Forte@Sun.COM 	(void) close(fd);
4937836SJohn.Forte@Sun.COM 	return (ret);
4947836SJohn.Forte@Sun.COM }
4957836SJohn.Forte@Sun.COM 
4967836SJohn.Forte@Sun.COM /*
4977836SJohn.Forte@Sun.COM  * stmfAddToTargetGroup
4987836SJohn.Forte@Sun.COM  *
4997836SJohn.Forte@Sun.COM  * Purpose: Adds a local port to an existing target group
5007836SJohn.Forte@Sun.COM  *
5017836SJohn.Forte@Sun.COM  * targetGroupName - name of an existing target group
5027836SJohn.Forte@Sun.COM  * targetName - name of target to add
5037836SJohn.Forte@Sun.COM  */
5047836SJohn.Forte@Sun.COM int
5057836SJohn.Forte@Sun.COM stmfAddToTargetGroup(stmfGroupName *targetGroupName, stmfDevid *targetName)
5067836SJohn.Forte@Sun.COM {
5077836SJohn.Forte@Sun.COM 	int ret;
5087836SJohn.Forte@Sun.COM 	int fd;
5097836SJohn.Forte@Sun.COM 	stmfState state;
5107836SJohn.Forte@Sun.COM 
5117836SJohn.Forte@Sun.COM 	if (targetGroupName == NULL ||
5127836SJohn.Forte@Sun.COM 	    (strnlen((char *)targetGroupName, sizeof (stmfGroupName))
5137836SJohn.Forte@Sun.COM 	    == sizeof (stmfGroupName)) || targetName == NULL) {
5147836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
5157836SJohn.Forte@Sun.COM 	}
5167836SJohn.Forte@Sun.COM 
5177836SJohn.Forte@Sun.COM 	ret = stmfGetState(&state);
5187836SJohn.Forte@Sun.COM 	if (ret == STMF_STATUS_SUCCESS) {
5197836SJohn.Forte@Sun.COM 		if (state.operationalState != STMF_SERVICE_STATE_OFFLINE) {
5207836SJohn.Forte@Sun.COM 			return (STMF_ERROR_SERVICE_ONLINE);
5217836SJohn.Forte@Sun.COM 		}
5227836SJohn.Forte@Sun.COM 	} else {
5237836SJohn.Forte@Sun.COM 		return (STMF_STATUS_ERROR);
5247836SJohn.Forte@Sun.COM 	}
5257836SJohn.Forte@Sun.COM 
5267836SJohn.Forte@Sun.COM 	/* call init */
5277836SJohn.Forte@Sun.COM 	ret = initializeConfig();
5287836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
5297836SJohn.Forte@Sun.COM 		return (ret);
5307836SJohn.Forte@Sun.COM 	}
5317836SJohn.Forte@Sun.COM 
5327836SJohn.Forte@Sun.COM 	/*
5337836SJohn.Forte@Sun.COM 	 * Open control node for stmf
5347836SJohn.Forte@Sun.COM 	 */
5357836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
5367836SJohn.Forte@Sun.COM 		return (ret);
5377836SJohn.Forte@Sun.COM 
5387836SJohn.Forte@Sun.COM 	if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_TG_ENTRY,
5397836SJohn.Forte@Sun.COM 	    targetGroupName, targetName)) != STMF_STATUS_SUCCESS) {
5407836SJohn.Forte@Sun.COM 		goto done;
5417836SJohn.Forte@Sun.COM 	}
5427836SJohn.Forte@Sun.COM 
543*9585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
544*9585STim.Szeto@Sun.COM 		goto done;
545*9585STim.Szeto@Sun.COM 	}
546*9585STim.Szeto@Sun.COM 
5477836SJohn.Forte@Sun.COM 	ret = psAddTargetGroupMember((char *)targetGroupName,
5487836SJohn.Forte@Sun.COM 	    (char *)targetName->ident);
5497836SJohn.Forte@Sun.COM 	switch (ret) {
5507836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
5517836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
5527836SJohn.Forte@Sun.COM 			break;
5537836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_EXISTS:
5547836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_EXISTS;
5557836SJohn.Forte@Sun.COM 			break;
5567836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_GROUP_NOT_FOUND:
5577836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_GROUP_NOT_FOUND;
5587836SJohn.Forte@Sun.COM 			break;
5597836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
5607836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
5617836SJohn.Forte@Sun.COM 			break;
5627836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
5637836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
5647836SJohn.Forte@Sun.COM 			break;
5657836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
5667836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
5677836SJohn.Forte@Sun.COM 			break;
5687836SJohn.Forte@Sun.COM 		default:
5697836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
5707836SJohn.Forte@Sun.COM 			    "stmfAddToTargetGroup:psAddTargetGroupMember:"
5717836SJohn.Forte@Sun.COM 			    "error(%d)", ret);
5727836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
5737836SJohn.Forte@Sun.COM 			break;
5747836SJohn.Forte@Sun.COM 	}
5757836SJohn.Forte@Sun.COM 
5767836SJohn.Forte@Sun.COM done:
5777836SJohn.Forte@Sun.COM 	(void) close(fd);
5787836SJohn.Forte@Sun.COM 	return (ret);
5797836SJohn.Forte@Sun.COM }
5807836SJohn.Forte@Sun.COM 
5817836SJohn.Forte@Sun.COM /*
5827836SJohn.Forte@Sun.COM  * addViewEntryIoctl
5837836SJohn.Forte@Sun.COM  *
5847836SJohn.Forte@Sun.COM  * Purpose: Issues ioctl to add a view entry
5857836SJohn.Forte@Sun.COM  *
5867836SJohn.Forte@Sun.COM  * lu - Logical Unit identifier to which the view entry is added
5877836SJohn.Forte@Sun.COM  * viewEntry - view entry to add
5887836SJohn.Forte@Sun.COM  * init - When set to B_TRUE, we are in the init state, i.e. don't call open
5897836SJohn.Forte@Sun.COM  */
5907836SJohn.Forte@Sun.COM static int
5917836SJohn.Forte@Sun.COM addViewEntryIoctl(int fd, stmfGuid *lu, stmfViewEntry *viewEntry)
5927836SJohn.Forte@Sun.COM {
5937836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
5947836SJohn.Forte@Sun.COM 	int ioctlRet;
5957836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
5967836SJohn.Forte@Sun.COM 	stmf_view_op_entry_t ioctlViewEntry;
5977836SJohn.Forte@Sun.COM 
5987836SJohn.Forte@Sun.COM 	bzero(&ioctlViewEntry, sizeof (ioctlViewEntry));
5997836SJohn.Forte@Sun.COM 	/*
6007836SJohn.Forte@Sun.COM 	 * don't set ve_ndx or ve_ndx_valid as ve_ndx_valid should be
6017836SJohn.Forte@Sun.COM 	 * false on input
6027836SJohn.Forte@Sun.COM 	 */
6037836SJohn.Forte@Sun.COM 	ioctlViewEntry.ve_lu_number_valid = viewEntry->luNbrValid;
6047836SJohn.Forte@Sun.COM 	ioctlViewEntry.ve_all_hosts = viewEntry->allHosts;
6057836SJohn.Forte@Sun.COM 	ioctlViewEntry.ve_all_targets = viewEntry->allTargets;
6067836SJohn.Forte@Sun.COM 
6077836SJohn.Forte@Sun.COM 	if (viewEntry->allHosts == B_FALSE) {
6087836SJohn.Forte@Sun.COM 		bcopy(viewEntry->hostGroup, &ioctlViewEntry.ve_host_group.name,
6097836SJohn.Forte@Sun.COM 		    sizeof (stmfGroupName));
6107836SJohn.Forte@Sun.COM 		ioctlViewEntry.ve_host_group.name_size =
6117836SJohn.Forte@Sun.COM 		    strlen((char *)viewEntry->hostGroup);
6127836SJohn.Forte@Sun.COM 	}
6137836SJohn.Forte@Sun.COM 	if (viewEntry->allTargets == B_FALSE) {
6147836SJohn.Forte@Sun.COM 		bcopy(viewEntry->targetGroup,
6157836SJohn.Forte@Sun.COM 		    &ioctlViewEntry.ve_target_group.name,
6167836SJohn.Forte@Sun.COM 		    sizeof (stmfGroupName));
6177836SJohn.Forte@Sun.COM 		ioctlViewEntry.ve_target_group.name_size =
6187836SJohn.Forte@Sun.COM 		    strlen((char *)viewEntry->targetGroup);
6197836SJohn.Forte@Sun.COM 	}
6207836SJohn.Forte@Sun.COM 	if (viewEntry->luNbrValid) {
6217836SJohn.Forte@Sun.COM 		bcopy(viewEntry->luNbr, &ioctlViewEntry.ve_lu_nbr,
6227836SJohn.Forte@Sun.COM 		    sizeof (ioctlViewEntry.ve_lu_nbr));
6237836SJohn.Forte@Sun.COM 	}
6247836SJohn.Forte@Sun.COM 	bcopy(lu, &ioctlViewEntry.ve_guid, sizeof (stmfGuid));
6257836SJohn.Forte@Sun.COM 
6267836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
6277836SJohn.Forte@Sun.COM 	/*
6287836SJohn.Forte@Sun.COM 	 * Issue ioctl to add to the view entry
6297836SJohn.Forte@Sun.COM 	 */
6307836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
6317836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry);
6327836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry;
6337836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = sizeof (ioctlViewEntry);
6347836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&ioctlViewEntry;
6357836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_ADD_VIEW_ENTRY, &stmfIoctl);
6367836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
6377836SJohn.Forte@Sun.COM 		switch (errno) {
6387836SJohn.Forte@Sun.COM 			case EBUSY:
6397836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
6407836SJohn.Forte@Sun.COM 				break;
641*9585STim.Szeto@Sun.COM 			case EPERM:
642*9585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
643*9585STim.Szeto@Sun.COM 				break;
6447836SJohn.Forte@Sun.COM 			case EACCES:
6457836SJohn.Forte@Sun.COM 				switch (stmfIoctl.stmf_error) {
6467836SJohn.Forte@Sun.COM 					case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
6477836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_CONFIG_NONE;
6487836SJohn.Forte@Sun.COM 						break;
6497836SJohn.Forte@Sun.COM 					default:
6507836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_PERM;
6517836SJohn.Forte@Sun.COM 						break;
6527836SJohn.Forte@Sun.COM 				}
6537836SJohn.Forte@Sun.COM 				break;
6547836SJohn.Forte@Sun.COM 			default:
6557836SJohn.Forte@Sun.COM 				switch (stmfIoctl.stmf_error) {
6567836SJohn.Forte@Sun.COM 					case STMF_IOCERR_LU_NUMBER_IN_USE:
6577836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_LUN_IN_USE;
6587836SJohn.Forte@Sun.COM 						break;
6597836SJohn.Forte@Sun.COM 					case STMF_IOCERR_VIEW_ENTRY_CONFLICT:
6607836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_VE_CONFLICT;
6617836SJohn.Forte@Sun.COM 						break;
6627836SJohn.Forte@Sun.COM 					case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
6637836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_CONFIG_NONE;
6647836SJohn.Forte@Sun.COM 						break;
6657836SJohn.Forte@Sun.COM 					case STMF_IOCERR_INVALID_HG:
6667836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_INVALID_HG;
6677836SJohn.Forte@Sun.COM 						break;
6687836SJohn.Forte@Sun.COM 					case STMF_IOCERR_INVALID_TG:
6697836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_INVALID_TG;
6707836SJohn.Forte@Sun.COM 						break;
6717836SJohn.Forte@Sun.COM 					default:
6727836SJohn.Forte@Sun.COM 						syslog(LOG_DEBUG,
6737836SJohn.Forte@Sun.COM 						    "addViewEntryIoctl"
6747836SJohn.Forte@Sun.COM 						    ":error(%d)",
6757836SJohn.Forte@Sun.COM 						    stmfIoctl.stmf_error);
6767836SJohn.Forte@Sun.COM 						ret = STMF_STATUS_ERROR;
6777836SJohn.Forte@Sun.COM 						break;
6787836SJohn.Forte@Sun.COM 				}
6797836SJohn.Forte@Sun.COM 				break;
6807836SJohn.Forte@Sun.COM 		}
6817836SJohn.Forte@Sun.COM 		goto done;
6827836SJohn.Forte@Sun.COM 	}
6837836SJohn.Forte@Sun.COM 
6847836SJohn.Forte@Sun.COM 	/* copy lu nbr back to caller's view entry on success */
6857836SJohn.Forte@Sun.COM 	viewEntry->veIndex = ioctlViewEntry.ve_ndx;
6867836SJohn.Forte@Sun.COM 	if (ioctlViewEntry.ve_lu_number_valid) {
6877836SJohn.Forte@Sun.COM 		bcopy(&ioctlViewEntry.ve_lu_nbr, viewEntry->luNbr,
6887836SJohn.Forte@Sun.COM 		    sizeof (ioctlViewEntry.ve_lu_nbr));
6897836SJohn.Forte@Sun.COM 	}
6907836SJohn.Forte@Sun.COM 	viewEntry->luNbrValid = B_TRUE;
6917836SJohn.Forte@Sun.COM 
6927836SJohn.Forte@Sun.COM done:
6937836SJohn.Forte@Sun.COM 	return (ret);
6947836SJohn.Forte@Sun.COM }
6957836SJohn.Forte@Sun.COM 
6967836SJohn.Forte@Sun.COM /*
6977836SJohn.Forte@Sun.COM  * stmfAddViewEntry
6987836SJohn.Forte@Sun.COM  *
6997836SJohn.Forte@Sun.COM  * Purpose: Adds a view entry to a logical unit
7007836SJohn.Forte@Sun.COM  *
7017836SJohn.Forte@Sun.COM  * lu - guid of the logical unit to which the view entry is added
7027836SJohn.Forte@Sun.COM  * viewEntry - view entry structure to add
7037836SJohn.Forte@Sun.COM  */
7047836SJohn.Forte@Sun.COM int
7057836SJohn.Forte@Sun.COM stmfAddViewEntry(stmfGuid *lu, stmfViewEntry *viewEntry)
7067836SJohn.Forte@Sun.COM {
7077836SJohn.Forte@Sun.COM 	int ret;
7087836SJohn.Forte@Sun.COM 	int fd;
7097836SJohn.Forte@Sun.COM 	stmfViewEntry iViewEntry;
7107836SJohn.Forte@Sun.COM 
7117836SJohn.Forte@Sun.COM 	if (lu == NULL || viewEntry == NULL) {
7127836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
7137836SJohn.Forte@Sun.COM 	}
7147836SJohn.Forte@Sun.COM 
7157836SJohn.Forte@Sun.COM 	/* initialize and set internal view entry */
7167836SJohn.Forte@Sun.COM 	bzero(&iViewEntry, sizeof (iViewEntry));
7177836SJohn.Forte@Sun.COM 
7187836SJohn.Forte@Sun.COM 	if (!viewEntry->allHosts) {
7197836SJohn.Forte@Sun.COM 		bcopy(viewEntry->hostGroup, iViewEntry.hostGroup,
7207836SJohn.Forte@Sun.COM 		    sizeof (iViewEntry.hostGroup));
7217836SJohn.Forte@Sun.COM 	} else {
7227836SJohn.Forte@Sun.COM 		iViewEntry.allHosts = B_TRUE;
7237836SJohn.Forte@Sun.COM 	}
7247836SJohn.Forte@Sun.COM 
7257836SJohn.Forte@Sun.COM 	if (!viewEntry->allTargets) {
7267836SJohn.Forte@Sun.COM 		bcopy(viewEntry->targetGroup, iViewEntry.targetGroup,
7277836SJohn.Forte@Sun.COM 		    sizeof (iViewEntry.targetGroup));
7287836SJohn.Forte@Sun.COM 	} else {
7297836SJohn.Forte@Sun.COM 		iViewEntry.allTargets = B_TRUE;
7307836SJohn.Forte@Sun.COM 	}
7317836SJohn.Forte@Sun.COM 
7327836SJohn.Forte@Sun.COM 	if (viewEntry->luNbrValid) {
7337836SJohn.Forte@Sun.COM 		iViewEntry.luNbrValid = B_TRUE;
7347836SJohn.Forte@Sun.COM 		bcopy(viewEntry->luNbr, iViewEntry.luNbr,
7357836SJohn.Forte@Sun.COM 		    sizeof (iViewEntry.luNbr));
7367836SJohn.Forte@Sun.COM 	}
7377836SJohn.Forte@Sun.COM 
7387836SJohn.Forte@Sun.COM 	/*
7397836SJohn.Forte@Sun.COM 	 * set users return view entry index valid flag to false
7407836SJohn.Forte@Sun.COM 	 * in case of failure
7417836SJohn.Forte@Sun.COM 	 */
7427836SJohn.Forte@Sun.COM 	viewEntry->veIndexValid = B_FALSE;
7437836SJohn.Forte@Sun.COM 
7447836SJohn.Forte@Sun.COM 	/* Check to ensure service exists */
7457836SJohn.Forte@Sun.COM 	if (psCheckService() != STMF_STATUS_SUCCESS) {
7467836SJohn.Forte@Sun.COM 		return (STMF_ERROR_SERVICE_NOT_FOUND);
7477836SJohn.Forte@Sun.COM 	}
7487836SJohn.Forte@Sun.COM 
7497836SJohn.Forte@Sun.COM 	/* call init */
7507836SJohn.Forte@Sun.COM 	ret = initializeConfig();
7517836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
7527836SJohn.Forte@Sun.COM 		return (ret);
7537836SJohn.Forte@Sun.COM 	}
7547836SJohn.Forte@Sun.COM 
7557836SJohn.Forte@Sun.COM 	/*
7567836SJohn.Forte@Sun.COM 	 * Open control node for stmf
7577836SJohn.Forte@Sun.COM 	 */
7587836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
7597836SJohn.Forte@Sun.COM 		return (ret);
7607836SJohn.Forte@Sun.COM 
7617836SJohn.Forte@Sun.COM 	/*
7627836SJohn.Forte@Sun.COM 	 * First add the view entry to the driver
7637836SJohn.Forte@Sun.COM 	 */
7647836SJohn.Forte@Sun.COM 	ret = addViewEntryIoctl(fd, lu, &iViewEntry);
7657836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
7667836SJohn.Forte@Sun.COM 		goto done;
7677836SJohn.Forte@Sun.COM 	}
7687836SJohn.Forte@Sun.COM 
769*9585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
770*9585STim.Szeto@Sun.COM 		goto done;
771*9585STim.Szeto@Sun.COM 	}
772*9585STim.Szeto@Sun.COM 
7737836SJohn.Forte@Sun.COM 	/*
7747836SJohn.Forte@Sun.COM 	 * If the add to driver was successful, add it to the persistent
7757836SJohn.Forte@Sun.COM 	 * store.
7767836SJohn.Forte@Sun.COM 	 */
7777836SJohn.Forte@Sun.COM 	ret = psAddViewEntry(lu, &iViewEntry);
7787836SJohn.Forte@Sun.COM 	switch (ret) {
7797836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
7807836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
7817836SJohn.Forte@Sun.COM 			break;
7827836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
7837836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
7847836SJohn.Forte@Sun.COM 			break;
7857836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
7867836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
7877836SJohn.Forte@Sun.COM 			break;
7887836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
7897836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
7907836SJohn.Forte@Sun.COM 			break;
7917836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
7927836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
7937836SJohn.Forte@Sun.COM 			break;
7947836SJohn.Forte@Sun.COM 		default:
7957836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
7967836SJohn.Forte@Sun.COM 			    "stmfAddViewEntry:psAddViewEntry:error(%d)", ret);
7977836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
7987836SJohn.Forte@Sun.COM 			break;
7997836SJohn.Forte@Sun.COM 	}
8007836SJohn.Forte@Sun.COM 
8017836SJohn.Forte@Sun.COM done:
8027836SJohn.Forte@Sun.COM 	(void) close(fd);
8037836SJohn.Forte@Sun.COM 
8047836SJohn.Forte@Sun.COM 	if (ret == STMF_STATUS_SUCCESS) {
8057836SJohn.Forte@Sun.COM 		/* set caller's view entry on success */
8067836SJohn.Forte@Sun.COM 		viewEntry->veIndexValid = iViewEntry.veIndexValid;
8077836SJohn.Forte@Sun.COM 		viewEntry->veIndex = iViewEntry.veIndex;
8087836SJohn.Forte@Sun.COM 		viewEntry->luNbrValid = B_TRUE;
8097836SJohn.Forte@Sun.COM 		bcopy(iViewEntry.luNbr, viewEntry->luNbr,
8107836SJohn.Forte@Sun.COM 		    sizeof (iViewEntry.luNbr));
8117836SJohn.Forte@Sun.COM 	}
8127836SJohn.Forte@Sun.COM 	return (ret);
8137836SJohn.Forte@Sun.COM }
8147836SJohn.Forte@Sun.COM 
8157836SJohn.Forte@Sun.COM /*
8167836SJohn.Forte@Sun.COM  * stmfClearProviderData
8177836SJohn.Forte@Sun.COM  *
8187836SJohn.Forte@Sun.COM  * Purpose: delete all provider data for specified provider
8197836SJohn.Forte@Sun.COM  *
8207836SJohn.Forte@Sun.COM  * providerName - name of provider for which data should be deleted
8217836SJohn.Forte@Sun.COM  */
8227836SJohn.Forte@Sun.COM int
8237836SJohn.Forte@Sun.COM stmfClearProviderData(char *providerName, int providerType)
8247836SJohn.Forte@Sun.COM {
8257836SJohn.Forte@Sun.COM 	int ret;
8267836SJohn.Forte@Sun.COM 	int fd;
8277836SJohn.Forte@Sun.COM 	int ioctlRet;
8287836SJohn.Forte@Sun.COM 	int savedErrno;
8297836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
8307836SJohn.Forte@Sun.COM 	stmf_ppioctl_data_t ppi;
8317836SJohn.Forte@Sun.COM 
8327836SJohn.Forte@Sun.COM 	/* call init */
8337836SJohn.Forte@Sun.COM 	ret = initializeConfig();
8347836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
8357836SJohn.Forte@Sun.COM 		return (ret);
8367836SJohn.Forte@Sun.COM 	}
8377836SJohn.Forte@Sun.COM 
8387836SJohn.Forte@Sun.COM 	if (providerName == NULL) {
8397836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
8407836SJohn.Forte@Sun.COM 	}
8417836SJohn.Forte@Sun.COM 
8427836SJohn.Forte@Sun.COM 	if (providerType != STMF_LU_PROVIDER_TYPE &&
8437836SJohn.Forte@Sun.COM 	    providerType != STMF_PORT_PROVIDER_TYPE) {
8447836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
8457836SJohn.Forte@Sun.COM 	}
8467836SJohn.Forte@Sun.COM 
8477836SJohn.Forte@Sun.COM 	/*
8487836SJohn.Forte@Sun.COM 	 * Open control node for stmf
8497836SJohn.Forte@Sun.COM 	 */
8507836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
8517836SJohn.Forte@Sun.COM 		return (ret);
8527836SJohn.Forte@Sun.COM 
8537836SJohn.Forte@Sun.COM 	bzero(&ppi, sizeof (ppi));
8547836SJohn.Forte@Sun.COM 
8557836SJohn.Forte@Sun.COM 	(void) strncpy(ppi.ppi_name, providerName, sizeof (ppi.ppi_name));
8567836SJohn.Forte@Sun.COM 
8577836SJohn.Forte@Sun.COM 	switch (providerType) {
8587836SJohn.Forte@Sun.COM 		case STMF_LU_PROVIDER_TYPE:
8597836SJohn.Forte@Sun.COM 			ppi.ppi_lu_provider = 1;
8607836SJohn.Forte@Sun.COM 			break;
8617836SJohn.Forte@Sun.COM 		case STMF_PORT_PROVIDER_TYPE:
8627836SJohn.Forte@Sun.COM 			ppi.ppi_port_provider = 1;
8637836SJohn.Forte@Sun.COM 			break;
8647836SJohn.Forte@Sun.COM 		default:
8657836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_INVALID_ARG;
8667836SJohn.Forte@Sun.COM 			goto done;
8677836SJohn.Forte@Sun.COM 	}
8687836SJohn.Forte@Sun.COM 
8697836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
8707836SJohn.Forte@Sun.COM 
8717836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
8727836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (stmf_ppioctl_data_t);
8737836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ppi;
8747836SJohn.Forte@Sun.COM 
8757836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_CLEAR_PP_DATA, &stmfIoctl);
8767836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
8777836SJohn.Forte@Sun.COM 		savedErrno = errno;
8787836SJohn.Forte@Sun.COM 		switch (savedErrno) {
8797836SJohn.Forte@Sun.COM 			case EBUSY:
8807836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
8817836SJohn.Forte@Sun.COM 				break;
882*9585STim.Szeto@Sun.COM 			case EPERM:
8837836SJohn.Forte@Sun.COM 			case EACCES:
8847836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
8857836SJohn.Forte@Sun.COM 				break;
8867836SJohn.Forte@Sun.COM 			default:
8877836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
8887836SJohn.Forte@Sun.COM 				    "stmfClearProviderData:ioctl error(%d)",
8897836SJohn.Forte@Sun.COM 				    ioctlRet);
8907836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
8917836SJohn.Forte@Sun.COM 				break;
8927836SJohn.Forte@Sun.COM 		}
8937836SJohn.Forte@Sun.COM 		if (savedErrno != ENOENT) {
8947836SJohn.Forte@Sun.COM 			goto done;
8957836SJohn.Forte@Sun.COM 		}
8967836SJohn.Forte@Sun.COM 	}
8977836SJohn.Forte@Sun.COM 
898*9585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
899*9585STim.Szeto@Sun.COM 		goto done;
900*9585STim.Szeto@Sun.COM 	}
901*9585STim.Szeto@Sun.COM 
9027836SJohn.Forte@Sun.COM 	ret = psClearProviderData(providerName, providerType);
9037836SJohn.Forte@Sun.COM 	switch (ret) {
9047836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
9057836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
9067836SJohn.Forte@Sun.COM 			break;
9077836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
9087836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
9097836SJohn.Forte@Sun.COM 			break;
9107836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
9117836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
9127836SJohn.Forte@Sun.COM 			break;
9137836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
9147836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
9157836SJohn.Forte@Sun.COM 			break;
9167836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
9177836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
9187836SJohn.Forte@Sun.COM 			break;
9197836SJohn.Forte@Sun.COM 		default:
9207836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
9217836SJohn.Forte@Sun.COM 			    "stmfClearProviderData:psClearProviderData"
9227836SJohn.Forte@Sun.COM 			    ":error(%d)", ret);
9237836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
9247836SJohn.Forte@Sun.COM 			break;
9257836SJohn.Forte@Sun.COM 	}
9267836SJohn.Forte@Sun.COM 
9277836SJohn.Forte@Sun.COM done:
9287836SJohn.Forte@Sun.COM 	(void) close(fd);
9297836SJohn.Forte@Sun.COM 	return (ret);
9307836SJohn.Forte@Sun.COM }
9317836SJohn.Forte@Sun.COM 
9327836SJohn.Forte@Sun.COM /*
9337836SJohn.Forte@Sun.COM  * stmfCreateHostGroup
9347836SJohn.Forte@Sun.COM  *
9357836SJohn.Forte@Sun.COM  * Purpose: Create a new initiator group
9367836SJohn.Forte@Sun.COM  *
9377836SJohn.Forte@Sun.COM  * hostGroupName - name of host group to create
9387836SJohn.Forte@Sun.COM  */
9397836SJohn.Forte@Sun.COM int
9407836SJohn.Forte@Sun.COM stmfCreateHostGroup(stmfGroupName *hostGroupName)
9417836SJohn.Forte@Sun.COM {
9427836SJohn.Forte@Sun.COM 	int ret;
9437836SJohn.Forte@Sun.COM 	int fd;
9447836SJohn.Forte@Sun.COM 
9457836SJohn.Forte@Sun.COM 	if (hostGroupName == NULL ||
9467836SJohn.Forte@Sun.COM 	    (strnlen((char *)hostGroupName, sizeof (stmfGroupName))
9477836SJohn.Forte@Sun.COM 	    == sizeof (stmfGroupName))) {
9487836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
9497836SJohn.Forte@Sun.COM 	}
9507836SJohn.Forte@Sun.COM 
9517836SJohn.Forte@Sun.COM 	/* Check to ensure service exists */
9527836SJohn.Forte@Sun.COM 	if (psCheckService() != STMF_STATUS_SUCCESS) {
9537836SJohn.Forte@Sun.COM 		return (STMF_ERROR_SERVICE_NOT_FOUND);
9547836SJohn.Forte@Sun.COM 	}
9557836SJohn.Forte@Sun.COM 
9567836SJohn.Forte@Sun.COM 	/* call init */
9577836SJohn.Forte@Sun.COM 	ret = initializeConfig();
9587836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
9597836SJohn.Forte@Sun.COM 		return (ret);
9607836SJohn.Forte@Sun.COM 	}
9617836SJohn.Forte@Sun.COM 
9627836SJohn.Forte@Sun.COM 	/*
9637836SJohn.Forte@Sun.COM 	 * Open control node for stmf
9647836SJohn.Forte@Sun.COM 	 */
9657836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
9667836SJohn.Forte@Sun.COM 		return (ret);
9677836SJohn.Forte@Sun.COM 
9687836SJohn.Forte@Sun.COM 	if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_HOST_GROUP,
9697836SJohn.Forte@Sun.COM 	    hostGroupName)) != STMF_STATUS_SUCCESS) {
9707836SJohn.Forte@Sun.COM 		goto done;
9717836SJohn.Forte@Sun.COM 	}
9727836SJohn.Forte@Sun.COM 
973*9585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
974*9585STim.Szeto@Sun.COM 		goto done;
975*9585STim.Szeto@Sun.COM 	}
976*9585STim.Szeto@Sun.COM 
9777836SJohn.Forte@Sun.COM 	ret = psCreateHostGroup((char *)hostGroupName);
9787836SJohn.Forte@Sun.COM 	switch (ret) {
9797836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
9807836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
9817836SJohn.Forte@Sun.COM 			break;
9827836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_EXISTS:
9837836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_EXISTS;
9847836SJohn.Forte@Sun.COM 			break;
9857836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
9867836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
9877836SJohn.Forte@Sun.COM 			break;
9887836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
9897836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
9907836SJohn.Forte@Sun.COM 			break;
9917836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
9927836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
9937836SJohn.Forte@Sun.COM 			break;
9947836SJohn.Forte@Sun.COM 		default:
9957836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
9967836SJohn.Forte@Sun.COM 			    "stmfCreateHostGroup:psCreateHostGroup:error(%d)",
9977836SJohn.Forte@Sun.COM 			    ret);
9987836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
9997836SJohn.Forte@Sun.COM 			break;
10007836SJohn.Forte@Sun.COM 	}
10017836SJohn.Forte@Sun.COM 
10027836SJohn.Forte@Sun.COM done:
10037836SJohn.Forte@Sun.COM 	(void) close(fd);
10047836SJohn.Forte@Sun.COM 	return (ret);
10057836SJohn.Forte@Sun.COM }
10067836SJohn.Forte@Sun.COM 
10077836SJohn.Forte@Sun.COM /*
1008*9585STim.Szeto@Sun.COM  * stmfCreateLu
1009*9585STim.Szeto@Sun.COM  *
1010*9585STim.Szeto@Sun.COM  * Purpose: Create a logical unit
1011*9585STim.Szeto@Sun.COM  *
1012*9585STim.Szeto@Sun.COM  * hdl - handle to logical unit resource created via stmfCreateLuResource
1013*9585STim.Szeto@Sun.COM  *
1014*9585STim.Szeto@Sun.COM  * luGuid - If non-NULL, on success, contains the guid of the created logical
1015*9585STim.Szeto@Sun.COM  *	    unit
1016*9585STim.Szeto@Sun.COM  */
1017*9585STim.Szeto@Sun.COM int
1018*9585STim.Szeto@Sun.COM stmfCreateLu(luResource hdl, stmfGuid *luGuid)
1019*9585STim.Szeto@Sun.COM {
1020*9585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
1021*9585STim.Szeto@Sun.COM 	luResourceImpl *luPropsHdl = hdl;
1022*9585STim.Szeto@Sun.COM 
1023*9585STim.Szeto@Sun.COM 	if (hdl == NULL) {
1024*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
1025*9585STim.Szeto@Sun.COM 	}
1026*9585STim.Szeto@Sun.COM 
1027*9585STim.Szeto@Sun.COM 	if (luPropsHdl->type == STMF_DISK) {
1028*9585STim.Szeto@Sun.COM 		ret = createDiskLu((diskResource *)luPropsHdl->resource,
1029*9585STim.Szeto@Sun.COM 		    luGuid);
1030*9585STim.Szeto@Sun.COM 	} else {
1031*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
1032*9585STim.Szeto@Sun.COM 	}
1033*9585STim.Szeto@Sun.COM 
1034*9585STim.Szeto@Sun.COM 	return (ret);
1035*9585STim.Szeto@Sun.COM }
1036*9585STim.Szeto@Sun.COM 
1037*9585STim.Szeto@Sun.COM /*
1038*9585STim.Szeto@Sun.COM  * stmfCreateLuResource
1039*9585STim.Szeto@Sun.COM  *
1040*9585STim.Szeto@Sun.COM  * Purpose: Create resource handle for a logical unit
1041*9585STim.Szeto@Sun.COM  *
1042*9585STim.Szeto@Sun.COM  * dType - Type of logical unit resource to create
1043*9585STim.Szeto@Sun.COM  *	   Can be: STMF_DISK
1044*9585STim.Szeto@Sun.COM  *
1045*9585STim.Szeto@Sun.COM  * hdl - pointer to luResource
1046*9585STim.Szeto@Sun.COM  */
1047*9585STim.Szeto@Sun.COM int
1048*9585STim.Szeto@Sun.COM stmfCreateLuResource(uint16_t dType, luResource *hdl)
1049*9585STim.Szeto@Sun.COM {
1050*9585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
1051*9585STim.Szeto@Sun.COM 
1052*9585STim.Szeto@Sun.COM 	if (dType != STMF_DISK || hdl == NULL) {
1053*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
1054*9585STim.Szeto@Sun.COM 	}
1055*9585STim.Szeto@Sun.COM 
1056*9585STim.Szeto@Sun.COM 	*hdl = calloc(1, sizeof (luResourceImpl));
1057*9585STim.Szeto@Sun.COM 	if (*hdl == NULL) {
1058*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_NOMEM);
1059*9585STim.Szeto@Sun.COM 	}
1060*9585STim.Szeto@Sun.COM 
1061*9585STim.Szeto@Sun.COM 	ret = createDiskResource((luResourceImpl *)*hdl);
1062*9585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
1063*9585STim.Szeto@Sun.COM 		free(*hdl);
1064*9585STim.Szeto@Sun.COM 		return (ret);
1065*9585STim.Szeto@Sun.COM 	}
1066*9585STim.Szeto@Sun.COM 
1067*9585STim.Szeto@Sun.COM 	return (STMF_STATUS_SUCCESS);
1068*9585STim.Szeto@Sun.COM }
1069*9585STim.Szeto@Sun.COM 
1070*9585STim.Szeto@Sun.COM /*
1071*9585STim.Szeto@Sun.COM  * Creates a disk logical unit
1072*9585STim.Szeto@Sun.COM  *
1073*9585STim.Szeto@Sun.COM  * disk - pointer to diskResource structure that represents the properties
1074*9585STim.Szeto@Sun.COM  *        for the disk logical unit to be created.
1075*9585STim.Szeto@Sun.COM  */
1076*9585STim.Szeto@Sun.COM static int
1077*9585STim.Szeto@Sun.COM createDiskLu(diskResource *disk, stmfGuid *createdGuid)
1078*9585STim.Szeto@Sun.COM {
1079*9585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
1080*9585STim.Szeto@Sun.COM 	int dataFileNameLen = 0;
1081*9585STim.Szeto@Sun.COM 	int metaFileNameLen = 0;
1082*9585STim.Szeto@Sun.COM 	int serialNumLen = 0;
1083*9585STim.Szeto@Sun.COM 	int luAliasLen = 0;
1084*9585STim.Szeto@Sun.COM 	int sluBufSize = 0;
1085*9585STim.Szeto@Sun.COM 	int bufOffset = 0;
1086*9585STim.Szeto@Sun.COM 	int fd = 0;
1087*9585STim.Szeto@Sun.COM 	int ioctlRet;
1088*9585STim.Szeto@Sun.COM 	int savedErrno;
1089*9585STim.Szeto@Sun.COM 	stmfGuid guid;
1090*9585STim.Szeto@Sun.COM 	stmf_iocdata_t sbdIoctl = {0};
1091*9585STim.Szeto@Sun.COM 
1092*9585STim.Szeto@Sun.COM 	sbd_create_and_reg_lu_t *sbdLu = NULL;
1093*9585STim.Szeto@Sun.COM 
1094*9585STim.Szeto@Sun.COM 	/*
1095*9585STim.Szeto@Sun.COM 	 * Open control node for sbd
1096*9585STim.Szeto@Sun.COM 	 */
1097*9585STim.Szeto@Sun.COM 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
1098*9585STim.Szeto@Sun.COM 		return (ret);
1099*9585STim.Szeto@Sun.COM 
1100*9585STim.Szeto@Sun.COM 	/* data file name must be specified */
1101*9585STim.Szeto@Sun.COM 	if (disk->luDataFileNameValid) {
1102*9585STim.Szeto@Sun.COM 		dataFileNameLen = strlen(disk->luDataFileName);
1103*9585STim.Szeto@Sun.COM 	} else {
1104*9585STim.Szeto@Sun.COM 		(void) close(fd);
1105*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_MISSING_PROP_VAL);
1106*9585STim.Szeto@Sun.COM 	}
1107*9585STim.Szeto@Sun.COM 
1108*9585STim.Szeto@Sun.COM 	sluBufSize += dataFileNameLen + 1;
1109*9585STim.Szeto@Sun.COM 
1110*9585STim.Szeto@Sun.COM 	if (disk->luMetaFileNameValid) {
1111*9585STim.Szeto@Sun.COM 		metaFileNameLen = strlen(disk->luMetaFileName);
1112*9585STim.Szeto@Sun.COM 		sluBufSize += metaFileNameLen + 1;
1113*9585STim.Szeto@Sun.COM 	}
1114*9585STim.Szeto@Sun.COM 
1115*9585STim.Szeto@Sun.COM 	serialNumLen = strlen(disk->serialNum);
1116*9585STim.Szeto@Sun.COM 	sluBufSize += serialNumLen;
1117*9585STim.Szeto@Sun.COM 
1118*9585STim.Szeto@Sun.COM 	if (disk->luAliasValid) {
1119*9585STim.Szeto@Sun.COM 		luAliasLen = strlen(disk->luAlias);
1120*9585STim.Szeto@Sun.COM 		sluBufSize += luAliasLen + 1;
1121*9585STim.Szeto@Sun.COM 	}
1122*9585STim.Szeto@Sun.COM 
1123*9585STim.Szeto@Sun.COM 	/*
1124*9585STim.Szeto@Sun.COM 	 * 8 is the size of the buffer set aside for
1125*9585STim.Szeto@Sun.COM 	 * concatenation of variable length fields
1126*9585STim.Szeto@Sun.COM 	 */
1127*9585STim.Szeto@Sun.COM 	sbdLu = (sbd_create_and_reg_lu_t *)calloc(1,
1128*9585STim.Szeto@Sun.COM 	    sizeof (sbd_create_and_reg_lu_t) + sluBufSize - 8);
1129*9585STim.Szeto@Sun.COM 	if (sbdLu == NULL) {
1130*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_NOMEM);
1131*9585STim.Szeto@Sun.COM 	}
1132*9585STim.Szeto@Sun.COM 
1133*9585STim.Szeto@Sun.COM 	sbdLu->slu_struct_size = sizeof (sbd_create_and_reg_lu_t) +
1134*9585STim.Szeto@Sun.COM 	    sluBufSize - 8;
1135*9585STim.Szeto@Sun.COM 
1136*9585STim.Szeto@Sun.COM 	if (metaFileNameLen) {
1137*9585STim.Szeto@Sun.COM 		sbdLu->slu_meta_fname_valid = 1;
1138*9585STim.Szeto@Sun.COM 		sbdLu->slu_meta_fname_off = bufOffset;
1139*9585STim.Szeto@Sun.COM 		bcopy(disk->luMetaFileName, &(sbdLu->slu_buf[bufOffset]),
1140*9585STim.Szeto@Sun.COM 		    metaFileNameLen + 1);
1141*9585STim.Szeto@Sun.COM 		bufOffset += metaFileNameLen + 1;
1142*9585STim.Szeto@Sun.COM 	}
1143*9585STim.Szeto@Sun.COM 
1144*9585STim.Szeto@Sun.COM 	bcopy(disk->luDataFileName, &(sbdLu->slu_buf[bufOffset]),
1145*9585STim.Szeto@Sun.COM 	    dataFileNameLen + 1);
1146*9585STim.Szeto@Sun.COM 	sbdLu->slu_data_fname_off = bufOffset;
1147*9585STim.Szeto@Sun.COM 	bufOffset += dataFileNameLen + 1;
1148*9585STim.Szeto@Sun.COM 
1149*9585STim.Szeto@Sun.COM 	/* currently, serial # is not passed null terminated to the driver */
1150*9585STim.Szeto@Sun.COM 	if (disk->serialNumValid) {
1151*9585STim.Szeto@Sun.COM 		sbdLu->slu_serial_valid = 1;
1152*9585STim.Szeto@Sun.COM 		sbdLu->slu_serial_off = bufOffset;
1153*9585STim.Szeto@Sun.COM 		sbdLu->slu_serial_size = serialNumLen;
1154*9585STim.Szeto@Sun.COM 		bcopy(disk->serialNum, &(sbdLu->slu_buf[bufOffset]),
1155*9585STim.Szeto@Sun.COM 		    serialNumLen);
1156*9585STim.Szeto@Sun.COM 		bufOffset += serialNumLen;
1157*9585STim.Szeto@Sun.COM 	}
1158*9585STim.Szeto@Sun.COM 
1159*9585STim.Szeto@Sun.COM 	if (disk->luAliasValid) {
1160*9585STim.Szeto@Sun.COM 		sbdLu->slu_alias_valid = 1;
1161*9585STim.Szeto@Sun.COM 		sbdLu->slu_alias_off = bufOffset;
1162*9585STim.Szeto@Sun.COM 		bcopy(disk->luAlias, &(sbdLu->slu_buf[bufOffset]),
1163*9585STim.Szeto@Sun.COM 		    luAliasLen + 1);
1164*9585STim.Szeto@Sun.COM 		bufOffset += luAliasLen + 1;
1165*9585STim.Szeto@Sun.COM 	}
1166*9585STim.Szeto@Sun.COM 
1167*9585STim.Szeto@Sun.COM 	if (disk->luSizeValid) {
1168*9585STim.Szeto@Sun.COM 		sbdLu->slu_lu_size_valid = 1;
1169*9585STim.Szeto@Sun.COM 		sbdLu->slu_lu_size = disk->luSize;
1170*9585STim.Szeto@Sun.COM 	}
1171*9585STim.Szeto@Sun.COM 
1172*9585STim.Szeto@Sun.COM 	if (disk->luGuidValid) {
1173*9585STim.Szeto@Sun.COM 		sbdLu->slu_guid_valid = 1;
1174*9585STim.Szeto@Sun.COM 		bcopy(disk->luGuid, sbdLu->slu_guid, sizeof (disk->luGuid));
1175*9585STim.Szeto@Sun.COM 	}
1176*9585STim.Szeto@Sun.COM 
1177*9585STim.Szeto@Sun.COM 	if (disk->vidValid) {
1178*9585STim.Szeto@Sun.COM 		sbdLu->slu_vid_valid = 1;
1179*9585STim.Szeto@Sun.COM 		bcopy(disk->vid, sbdLu->slu_vid, sizeof (disk->vid));
1180*9585STim.Szeto@Sun.COM 	}
1181*9585STim.Szeto@Sun.COM 
1182*9585STim.Szeto@Sun.COM 	if (disk->pidValid) {
1183*9585STim.Szeto@Sun.COM 		sbdLu->slu_pid_valid = 1;
1184*9585STim.Szeto@Sun.COM 		bcopy(disk->pid, sbdLu->slu_pid, sizeof (disk->pid));
1185*9585STim.Szeto@Sun.COM 	}
1186*9585STim.Szeto@Sun.COM 
1187*9585STim.Szeto@Sun.COM 	if (disk->revValid) {
1188*9585STim.Szeto@Sun.COM 		sbdLu->slu_rev_valid = 1;
1189*9585STim.Szeto@Sun.COM 		bcopy(disk->rev, sbdLu->slu_rev, sizeof (disk->rev));
1190*9585STim.Szeto@Sun.COM 	}
1191*9585STim.Szeto@Sun.COM 
1192*9585STim.Szeto@Sun.COM 	if (disk->companyIdValid) {
1193*9585STim.Szeto@Sun.COM 		sbdLu->slu_company_id_valid = 1;
1194*9585STim.Szeto@Sun.COM 		sbdLu->slu_company_id = disk->companyId;
1195*9585STim.Szeto@Sun.COM 	}
1196*9585STim.Szeto@Sun.COM 
1197*9585STim.Szeto@Sun.COM 	if (disk->blkSizeValid) {
1198*9585STim.Szeto@Sun.COM 		sbdLu->slu_blksize_valid = 1;
1199*9585STim.Szeto@Sun.COM 		sbdLu->slu_blksize = disk->blkSize;
1200*9585STim.Szeto@Sun.COM 	}
1201*9585STim.Szeto@Sun.COM 
1202*9585STim.Szeto@Sun.COM 	if (disk->writeProtectEnableValid) {
1203*9585STim.Szeto@Sun.COM 		if (disk->writeProtectEnable) {
1204*9585STim.Szeto@Sun.COM 			sbdLu->slu_write_protected = 1;
1205*9585STim.Szeto@Sun.COM 		}
1206*9585STim.Szeto@Sun.COM 	}
1207*9585STim.Szeto@Sun.COM 
1208*9585STim.Szeto@Sun.COM 	if (disk->writebackCacheDisableValid) {
1209*9585STim.Szeto@Sun.COM 		sbdLu->slu_writeback_cache_disable_valid = 1;
1210*9585STim.Szeto@Sun.COM 		if (disk->writebackCacheDisable) {
1211*9585STim.Szeto@Sun.COM 			sbdLu->slu_writeback_cache_disable = 1;
1212*9585STim.Szeto@Sun.COM 		}
1213*9585STim.Szeto@Sun.COM 	}
1214*9585STim.Szeto@Sun.COM 
1215*9585STim.Szeto@Sun.COM 	sbdIoctl.stmf_version = STMF_VERSION_1;
1216*9585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf_size = sbdLu->slu_struct_size;
1217*9585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdLu;
1218*9585STim.Szeto@Sun.COM 	sbdIoctl.stmf_obuf_size = sbdLu->slu_struct_size;
1219*9585STim.Szeto@Sun.COM 	sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdLu;
1220*9585STim.Szeto@Sun.COM 
1221*9585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, SBD_IOCTL_CREATE_AND_REGISTER_LU, &sbdIoctl);
1222*9585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
1223*9585STim.Szeto@Sun.COM 		savedErrno = errno;
1224*9585STim.Szeto@Sun.COM 		switch (savedErrno) {
1225*9585STim.Szeto@Sun.COM 			case EBUSY:
1226*9585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
1227*9585STim.Szeto@Sun.COM 				break;
1228*9585STim.Szeto@Sun.COM 			case EPERM:
1229*9585STim.Szeto@Sun.COM 			case EACCES:
1230*9585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
1231*9585STim.Szeto@Sun.COM 				break;
1232*9585STim.Szeto@Sun.COM 			default:
1233*9585STim.Szeto@Sun.COM 				diskError(sbdIoctl.stmf_error, &ret);
1234*9585STim.Szeto@Sun.COM 				if (ret == STMF_STATUS_ERROR) {
1235*9585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
1236*9585STim.Szeto@Sun.COM 					"createDiskLu:ioctl "
1237*9585STim.Szeto@Sun.COM 					"error(%d) (%d) (%d)", ioctlRet,
1238*9585STim.Szeto@Sun.COM 					    sbdIoctl.stmf_error, savedErrno);
1239*9585STim.Szeto@Sun.COM 				}
1240*9585STim.Szeto@Sun.COM 				break;
1241*9585STim.Szeto@Sun.COM 		}
1242*9585STim.Szeto@Sun.COM 	}
1243*9585STim.Szeto@Sun.COM 
1244*9585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
1245*9585STim.Szeto@Sun.COM 		goto done;
1246*9585STim.Szeto@Sun.COM 	}
1247*9585STim.Szeto@Sun.COM 
1248*9585STim.Szeto@Sun.COM 	/*
1249*9585STim.Szeto@Sun.COM 	 * on success, copy the resulting guid into the caller's guid if not
1250*9585STim.Szeto@Sun.COM 	 * NULL
1251*9585STim.Szeto@Sun.COM 	 */
1252*9585STim.Szeto@Sun.COM 	if (createdGuid) {
1253*9585STim.Szeto@Sun.COM 		bcopy(sbdLu->slu_guid, createdGuid->guid,
1254*9585STim.Szeto@Sun.COM 		    sizeof (sbdLu->slu_guid));
1255*9585STim.Szeto@Sun.COM 	}
1256*9585STim.Szeto@Sun.COM 
1257*9585STim.Szeto@Sun.COM 	bcopy(sbdLu->slu_guid, guid.guid, sizeof (sbdLu->slu_guid));
1258*9585STim.Szeto@Sun.COM 	if (disk->luMetaFileNameValid) {
1259*9585STim.Szeto@Sun.COM 		ret = addGuidToDiskStore(&guid, disk->luMetaFileName);
1260*9585STim.Szeto@Sun.COM 	} else {
1261*9585STim.Szeto@Sun.COM 		ret = addGuidToDiskStore(&guid, disk->luDataFileName);
1262*9585STim.Szeto@Sun.COM 	}
1263*9585STim.Szeto@Sun.COM done:
1264*9585STim.Szeto@Sun.COM 	free(sbdLu);
1265*9585STim.Szeto@Sun.COM 	(void) close(fd);
1266*9585STim.Szeto@Sun.COM 	return (ret);
1267*9585STim.Szeto@Sun.COM }
1268*9585STim.Szeto@Sun.COM 
1269*9585STim.Szeto@Sun.COM 
1270*9585STim.Szeto@Sun.COM /*
1271*9585STim.Szeto@Sun.COM  * stmfImportLu
1272*9585STim.Szeto@Sun.COM  *
1273*9585STim.Szeto@Sun.COM  * Purpose: Import a previously created logical unit
1274*9585STim.Szeto@Sun.COM  *
1275*9585STim.Szeto@Sun.COM  * dType - Type of logical unit
1276*9585STim.Szeto@Sun.COM  *         Can be: STMF_DISK
1277*9585STim.Szeto@Sun.COM  *
1278*9585STim.Szeto@Sun.COM  * luGuid - If non-NULL, on success, contains the guid of the imported logical
1279*9585STim.Szeto@Sun.COM  *	    unit
1280*9585STim.Szeto@Sun.COM  *
1281*9585STim.Szeto@Sun.COM  * fname - A file name where the metadata resides
1282*9585STim.Szeto@Sun.COM  *
1283*9585STim.Szeto@Sun.COM  */
1284*9585STim.Szeto@Sun.COM int
1285*9585STim.Szeto@Sun.COM stmfImportLu(uint16_t dType, char *fname, stmfGuid *luGuid)
1286*9585STim.Szeto@Sun.COM {
1287*9585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
1288*9585STim.Szeto@Sun.COM 
1289*9585STim.Szeto@Sun.COM 	if (dType == STMF_DISK) {
1290*9585STim.Szeto@Sun.COM 		ret = importDiskLu(fname, luGuid);
1291*9585STim.Szeto@Sun.COM 	} else {
1292*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
1293*9585STim.Szeto@Sun.COM 	}
1294*9585STim.Szeto@Sun.COM 
1295*9585STim.Szeto@Sun.COM 	return (ret);
1296*9585STim.Szeto@Sun.COM }
1297*9585STim.Szeto@Sun.COM 
1298*9585STim.Szeto@Sun.COM /*
1299*9585STim.Szeto@Sun.COM  * importDiskLu
1300*9585STim.Szeto@Sun.COM  *
1301*9585STim.Szeto@Sun.COM  * filename - filename to import
1302*9585STim.Szeto@Sun.COM  * createdGuid - if not NULL, on success contains the imported guid
1303*9585STim.Szeto@Sun.COM  *
1304*9585STim.Szeto@Sun.COM  */
1305*9585STim.Szeto@Sun.COM static int
1306*9585STim.Szeto@Sun.COM importDiskLu(char *fname, stmfGuid *createdGuid)
1307*9585STim.Szeto@Sun.COM {
1308*9585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
1309*9585STim.Szeto@Sun.COM 	int fd = 0;
1310*9585STim.Szeto@Sun.COM 	int ioctlRet;
1311*9585STim.Szeto@Sun.COM 	int savedErrno;
1312*9585STim.Szeto@Sun.COM 	int metaFileNameLen;
1313*9585STim.Szeto@Sun.COM 	stmfGuid iGuid;
1314*9585STim.Szeto@Sun.COM 	int iluBufSize = 0;
1315*9585STim.Szeto@Sun.COM 	sbd_import_lu_t *sbdLu = NULL;
1316*9585STim.Szeto@Sun.COM 	stmf_iocdata_t sbdIoctl = {0};
1317*9585STim.Szeto@Sun.COM 
1318*9585STim.Szeto@Sun.COM 	if (fname == NULL) {
1319*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
1320*9585STim.Szeto@Sun.COM 	}
1321*9585STim.Szeto@Sun.COM 
1322*9585STim.Szeto@Sun.COM 	/*
1323*9585STim.Szeto@Sun.COM 	 * Open control node for sbd
1324*9585STim.Szeto@Sun.COM 	 */
1325*9585STim.Szeto@Sun.COM 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
1326*9585STim.Szeto@Sun.COM 		return (ret);
1327*9585STim.Szeto@Sun.COM 
1328*9585STim.Szeto@Sun.COM 	metaFileNameLen = strlen(fname);
1329*9585STim.Szeto@Sun.COM 	iluBufSize += metaFileNameLen + 1;
1330*9585STim.Szeto@Sun.COM 
1331*9585STim.Szeto@Sun.COM 	/*
1332*9585STim.Szeto@Sun.COM 	 * 8 is the size of the buffer set aside for
1333*9585STim.Szeto@Sun.COM 	 * concatenation of variable length fields
1334*9585STim.Szeto@Sun.COM 	 */
1335*9585STim.Szeto@Sun.COM 	sbdLu = (sbd_import_lu_t *)calloc(1,
1336*9585STim.Szeto@Sun.COM 	    sizeof (sbd_import_lu_t) + iluBufSize - 8);
1337*9585STim.Szeto@Sun.COM 	if (sbdLu == NULL) {
1338*9585STim.Szeto@Sun.COM 		(void) close(fd);
1339*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_NOMEM);
1340*9585STim.Szeto@Sun.COM 	}
1341*9585STim.Szeto@Sun.COM 
1342*9585STim.Szeto@Sun.COM 	/*
1343*9585STim.Szeto@Sun.COM 	 * Accept either a data file or meta data file.
1344*9585STim.Szeto@Sun.COM 	 * sbd will do the right thing here either way.
1345*9585STim.Szeto@Sun.COM 	 * i.e. if it's a data file, it assumes that the
1346*9585STim.Szeto@Sun.COM 	 * meta data is shared with the data.
1347*9585STim.Szeto@Sun.COM 	 */
1348*9585STim.Szeto@Sun.COM 	(void) strncpy(sbdLu->ilu_meta_fname, fname, metaFileNameLen);
1349*9585STim.Szeto@Sun.COM 
1350*9585STim.Szeto@Sun.COM 	sbdLu->ilu_struct_size = sizeof (sbd_import_lu_t) + iluBufSize - 8;
1351*9585STim.Szeto@Sun.COM 
1352*9585STim.Szeto@Sun.COM 	sbdIoctl.stmf_version = STMF_VERSION_1;
1353*9585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf_size = sbdLu->ilu_struct_size;
1354*9585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdLu;
1355*9585STim.Szeto@Sun.COM 	sbdIoctl.stmf_obuf_size = sbdLu->ilu_struct_size;
1356*9585STim.Szeto@Sun.COM 	sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdLu;
1357*9585STim.Szeto@Sun.COM 
1358*9585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, SBD_IOCTL_IMPORT_LU, &sbdIoctl);
1359*9585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
1360*9585STim.Szeto@Sun.COM 		savedErrno = errno;
1361*9585STim.Szeto@Sun.COM 		switch (savedErrno) {
1362*9585STim.Szeto@Sun.COM 			case EBUSY:
1363*9585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
1364*9585STim.Szeto@Sun.COM 				break;
1365*9585STim.Szeto@Sun.COM 			case EPERM:
1366*9585STim.Szeto@Sun.COM 			case EACCES:
1367*9585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
1368*9585STim.Szeto@Sun.COM 				break;
1369*9585STim.Szeto@Sun.COM 			default:
1370*9585STim.Szeto@Sun.COM 				diskError(sbdIoctl.stmf_error, &ret);
1371*9585STim.Szeto@Sun.COM 				if (ret == STMF_STATUS_ERROR) {
1372*9585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
1373*9585STim.Szeto@Sun.COM 					"importDiskLu:ioctl "
1374*9585STim.Szeto@Sun.COM 					"error(%d) (%d) (%d)", ioctlRet,
1375*9585STim.Szeto@Sun.COM 					    sbdIoctl.stmf_error, savedErrno);
1376*9585STim.Szeto@Sun.COM 				}
1377*9585STim.Szeto@Sun.COM 				break;
1378*9585STim.Szeto@Sun.COM 		}
1379*9585STim.Szeto@Sun.COM 	}
1380*9585STim.Szeto@Sun.COM 
1381*9585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
1382*9585STim.Szeto@Sun.COM 		goto done;
1383*9585STim.Szeto@Sun.COM 	}
1384*9585STim.Szeto@Sun.COM 
1385*9585STim.Szeto@Sun.COM 	/*
1386*9585STim.Szeto@Sun.COM 	 * on success, copy the resulting guid into the caller's guid if not
1387*9585STim.Szeto@Sun.COM 	 * NULL and add it to the persistent store for sbd
1388*9585STim.Szeto@Sun.COM 	 */
1389*9585STim.Szeto@Sun.COM 	if (createdGuid) {
1390*9585STim.Szeto@Sun.COM 		bcopy(sbdLu->ilu_ret_guid, createdGuid->guid,
1391*9585STim.Szeto@Sun.COM 		    sizeof (sbdLu->ilu_ret_guid));
1392*9585STim.Szeto@Sun.COM 		ret = addGuidToDiskStore(createdGuid, fname);
1393*9585STim.Szeto@Sun.COM 	} else {
1394*9585STim.Szeto@Sun.COM 		bcopy(sbdLu->ilu_ret_guid, iGuid.guid,
1395*9585STim.Szeto@Sun.COM 		    sizeof (sbdLu->ilu_ret_guid));
1396*9585STim.Szeto@Sun.COM 		ret = addGuidToDiskStore(&iGuid, fname);
1397*9585STim.Szeto@Sun.COM 	}
1398*9585STim.Szeto@Sun.COM done:
1399*9585STim.Szeto@Sun.COM 	free(sbdLu);
1400*9585STim.Szeto@Sun.COM 	(void) close(fd);
1401*9585STim.Szeto@Sun.COM 	return (ret);
1402*9585STim.Szeto@Sun.COM }
1403*9585STim.Szeto@Sun.COM 
1404*9585STim.Szeto@Sun.COM /*
1405*9585STim.Szeto@Sun.COM  * diskError
1406*9585STim.Szeto@Sun.COM  *
1407*9585STim.Szeto@Sun.COM  * Purpose: Translate sbd driver error
1408*9585STim.Szeto@Sun.COM  */
1409*9585STim.Szeto@Sun.COM static void
1410*9585STim.Szeto@Sun.COM diskError(uint32_t stmfError, int *ret)
1411*9585STim.Szeto@Sun.COM {
1412*9585STim.Szeto@Sun.COM 	switch (stmfError) {
1413*9585STim.Szeto@Sun.COM 		case SBD_RET_META_CREATION_FAILED:
1414*9585STim.Szeto@Sun.COM 		case SBD_RET_ZFS_META_CREATE_FAILED:
1415*9585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_META_CREATION;
1416*9585STim.Szeto@Sun.COM 			break;
1417*9585STim.Szeto@Sun.COM 		case SBD_RET_INVALID_BLKSIZE:
1418*9585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_INVALID_BLKSIZE;
1419*9585STim.Szeto@Sun.COM 			break;
1420*9585STim.Szeto@Sun.COM 		case SBD_RET_FILE_ALREADY_REGISTERED:
1421*9585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_FILE_IN_USE;
1422*9585STim.Szeto@Sun.COM 			break;
1423*9585STim.Szeto@Sun.COM 		case SBD_RET_GUID_ALREADY_REGISTERED:
1424*9585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_GUID_IN_USE;
1425*9585STim.Szeto@Sun.COM 			break;
1426*9585STim.Szeto@Sun.COM 		case SBD_RET_META_PATH_NOT_ABSOLUTE:
1427*9585STim.Szeto@Sun.COM 		case SBD_RET_META_FILE_LOOKUP_FAILED:
1428*9585STim.Szeto@Sun.COM 		case SBD_RET_META_FILE_OPEN_FAILED:
1429*9585STim.Szeto@Sun.COM 		case SBD_RET_META_FILE_GETATTR_FAILED:
1430*9585STim.Szeto@Sun.COM 		case SBD_RET_NO_META:
1431*9585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_META_FILE_NAME;
1432*9585STim.Szeto@Sun.COM 			break;
1433*9585STim.Szeto@Sun.COM 		case SBD_RET_DATA_PATH_NOT_ABSOLUTE:
1434*9585STim.Szeto@Sun.COM 		case SBD_RET_DATA_FILE_LOOKUP_FAILED:
1435*9585STim.Szeto@Sun.COM 		case SBD_RET_DATA_FILE_OPEN_FAILED:
1436*9585STim.Szeto@Sun.COM 		case SBD_RET_DATA_FILE_GETATTR_FAILED:
1437*9585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_DATA_FILE_NAME;
1438*9585STim.Szeto@Sun.COM 			break;
1439*9585STim.Szeto@Sun.COM 		case SBD_RET_FILE_SIZE_ERROR:
1440*9585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_FILE_SIZE_INVALID;
1441*9585STim.Szeto@Sun.COM 			break;
1442*9585STim.Szeto@Sun.COM 		case SBD_RET_SIZE_OUT_OF_RANGE:
1443*9585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_SIZE_OUT_OF_RANGE;
1444*9585STim.Szeto@Sun.COM 			break;
1445*9585STim.Szeto@Sun.COM 		case SBD_RET_LU_BUSY:
1446*9585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_LU_BUSY;
1447*9585STim.Szeto@Sun.COM 			break;
1448*9585STim.Szeto@Sun.COM 		case SBD_RET_WRITE_CACHE_SET_FAILED:
1449*9585STim.Szeto@Sun.COM 			*ret = STMF_ERROR_WRITE_CACHE_SET;
1450*9585STim.Szeto@Sun.COM 			break;
1451*9585STim.Szeto@Sun.COM 		default:
1452*9585STim.Szeto@Sun.COM 			*ret = STMF_STATUS_ERROR;
1453*9585STim.Szeto@Sun.COM 			break;
1454*9585STim.Szeto@Sun.COM 	}
1455*9585STim.Szeto@Sun.COM }
1456*9585STim.Szeto@Sun.COM 
1457*9585STim.Szeto@Sun.COM /*
1458*9585STim.Szeto@Sun.COM  * Creates a logical unit resource of type STMF_DISK.
1459*9585STim.Szeto@Sun.COM  *
1460*9585STim.Szeto@Sun.COM  * No defaults should be set here as all defaults are derived from the
1461*9585STim.Szeto@Sun.COM  * driver's default settings.
1462*9585STim.Szeto@Sun.COM  */
1463*9585STim.Szeto@Sun.COM static int
1464*9585STim.Szeto@Sun.COM createDiskResource(luResourceImpl *hdl)
1465*9585STim.Szeto@Sun.COM {
1466*9585STim.Szeto@Sun.COM 	hdl->type = STMF_DISK;
1467*9585STim.Szeto@Sun.COM 
1468*9585STim.Szeto@Sun.COM 	hdl->resource = calloc(1, sizeof (diskResource));
1469*9585STim.Szeto@Sun.COM 	if (hdl->resource == NULL) {
1470*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_NOMEM);
1471*9585STim.Szeto@Sun.COM 	}
1472*9585STim.Szeto@Sun.COM 
1473*9585STim.Szeto@Sun.COM 	return (STMF_STATUS_SUCCESS);
1474*9585STim.Szeto@Sun.COM }
1475*9585STim.Szeto@Sun.COM 
1476*9585STim.Szeto@Sun.COM /*
1477*9585STim.Szeto@Sun.COM  * stmfDeleteLu
1478*9585STim.Szeto@Sun.COM  *
1479*9585STim.Szeto@Sun.COM  * Purpose: Delete a logical unit
1480*9585STim.Szeto@Sun.COM  *
1481*9585STim.Szeto@Sun.COM  * hdl - handle to logical unit resource created via stmfCreateLuResource
1482*9585STim.Szeto@Sun.COM  *
1483*9585STim.Szeto@Sun.COM  * luGuid - If non-NULL, on success, contains the guid of the created logical
1484*9585STim.Szeto@Sun.COM  *	    unit
1485*9585STim.Szeto@Sun.COM  */
1486*9585STim.Szeto@Sun.COM int
1487*9585STim.Szeto@Sun.COM stmfDeleteLu(stmfGuid *luGuid)
1488*9585STim.Szeto@Sun.COM {
1489*9585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
1490*9585STim.Szeto@Sun.COM 	stmfLogicalUnitProperties luProps;
1491*9585STim.Szeto@Sun.COM 
1492*9585STim.Szeto@Sun.COM 	if (luGuid == NULL) {
1493*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
1494*9585STim.Szeto@Sun.COM 	}
1495*9585STim.Szeto@Sun.COM 
1496*9585STim.Szeto@Sun.COM 	/* Check logical unit provider name to call correct dtype function */
1497*9585STim.Szeto@Sun.COM 	if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps))
1498*9585STim.Szeto@Sun.COM 	    != STMF_STATUS_SUCCESS) {
1499*9585STim.Szeto@Sun.COM 		return (ret);
1500*9585STim.Szeto@Sun.COM 	} else {
1501*9585STim.Szeto@Sun.COM 		if (strcmp(luProps.providerName, "sbd") == 0) {
1502*9585STim.Szeto@Sun.COM 			ret = deleteDiskLu(luGuid);
1503*9585STim.Szeto@Sun.COM 		} else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) {
1504*9585STim.Szeto@Sun.COM 			return (STMF_ERROR_NOT_FOUND);
1505*9585STim.Szeto@Sun.COM 		} else {
1506*9585STim.Szeto@Sun.COM 			return (STMF_ERROR_INVALID_ARG);
1507*9585STim.Szeto@Sun.COM 		}
1508*9585STim.Szeto@Sun.COM 	}
1509*9585STim.Szeto@Sun.COM 
1510*9585STim.Szeto@Sun.COM 	return (ret);
1511*9585STim.Szeto@Sun.COM }
1512*9585STim.Szeto@Sun.COM 
1513*9585STim.Szeto@Sun.COM static int
1514*9585STim.Szeto@Sun.COM deleteDiskLu(stmfGuid *luGuid)
1515*9585STim.Szeto@Sun.COM {
1516*9585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
1517*9585STim.Szeto@Sun.COM 	int fd;
1518*9585STim.Szeto@Sun.COM 	int savedErrno;
1519*9585STim.Szeto@Sun.COM 	int ioctlRet;
1520*9585STim.Szeto@Sun.COM 	sbd_delete_lu_t deleteLu = {0};
1521*9585STim.Szeto@Sun.COM 
1522*9585STim.Szeto@Sun.COM 	stmf_iocdata_t sbdIoctl = {0};
1523*9585STim.Szeto@Sun.COM 
1524*9585STim.Szeto@Sun.COM 	/*
1525*9585STim.Szeto@Sun.COM 	 * Open control node for sbd
1526*9585STim.Szeto@Sun.COM 	 */
1527*9585STim.Szeto@Sun.COM 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
1528*9585STim.Szeto@Sun.COM 		return (ret);
1529*9585STim.Szeto@Sun.COM 
1530*9585STim.Szeto@Sun.COM 	ret = removeGuidFromDiskStore(luGuid);
1531*9585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
1532*9585STim.Szeto@Sun.COM 		goto done;
1533*9585STim.Szeto@Sun.COM 	}
1534*9585STim.Szeto@Sun.COM 
1535*9585STim.Szeto@Sun.COM 	bcopy(luGuid, deleteLu.dlu_guid, sizeof (deleteLu.dlu_guid));
1536*9585STim.Szeto@Sun.COM 	deleteLu.dlu_by_guid = 1;
1537*9585STim.Szeto@Sun.COM 
1538*9585STim.Szeto@Sun.COM 	sbdIoctl.stmf_version = STMF_VERSION_1;
1539*9585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf_size = sizeof (deleteLu);
1540*9585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)&deleteLu;
1541*9585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, SBD_IOCTL_DELETE_LU, &sbdIoctl);
1542*9585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
1543*9585STim.Szeto@Sun.COM 		savedErrno = errno;
1544*9585STim.Szeto@Sun.COM 		switch (savedErrno) {
1545*9585STim.Szeto@Sun.COM 			case EBUSY:
1546*9585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
1547*9585STim.Szeto@Sun.COM 				break;
1548*9585STim.Szeto@Sun.COM 			case EPERM:
1549*9585STim.Szeto@Sun.COM 			case EACCES:
1550*9585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
1551*9585STim.Szeto@Sun.COM 				break;
1552*9585STim.Szeto@Sun.COM 			case ENOENT:
1553*9585STim.Szeto@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
1554*9585STim.Szeto@Sun.COM 				break;
1555*9585STim.Szeto@Sun.COM 			default:
1556*9585STim.Szeto@Sun.COM 				syslog(LOG_DEBUG,
1557*9585STim.Szeto@Sun.COM 				    "deleteDiskLu:ioctl error(%d) (%d) (%d)",
1558*9585STim.Szeto@Sun.COM 				    ioctlRet, sbdIoctl.stmf_error, savedErrno);
1559*9585STim.Szeto@Sun.COM 				ret = STMF_STATUS_ERROR;
1560*9585STim.Szeto@Sun.COM 				break;
1561*9585STim.Szeto@Sun.COM 		}
1562*9585STim.Szeto@Sun.COM 	}
1563*9585STim.Szeto@Sun.COM 
1564*9585STim.Szeto@Sun.COM done:
1565*9585STim.Szeto@Sun.COM 	(void) close(fd);
1566*9585STim.Szeto@Sun.COM 	return (ret);
1567*9585STim.Szeto@Sun.COM }
1568*9585STim.Szeto@Sun.COM 
1569*9585STim.Szeto@Sun.COM /*
1570*9585STim.Szeto@Sun.COM  * stmfModifyLu
1571*9585STim.Szeto@Sun.COM  *
1572*9585STim.Szeto@Sun.COM  * Purpose: Modify properties of a logical unit
1573*9585STim.Szeto@Sun.COM  *
1574*9585STim.Szeto@Sun.COM  * luGuid - guid of registered logical unit
1575*9585STim.Szeto@Sun.COM  * prop - property to modify
1576*9585STim.Szeto@Sun.COM  * propVal - property value to set
1577*9585STim.Szeto@Sun.COM  *
1578*9585STim.Szeto@Sun.COM  */
1579*9585STim.Szeto@Sun.COM int
1580*9585STim.Szeto@Sun.COM stmfModifyLu(stmfGuid *luGuid, uint32_t prop, const char *propVal)
1581*9585STim.Szeto@Sun.COM {
1582*9585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
1583*9585STim.Szeto@Sun.COM 	stmfLogicalUnitProperties luProps;
1584*9585STim.Szeto@Sun.COM 
1585*9585STim.Szeto@Sun.COM 	if (luGuid == NULL) {
1586*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
1587*9585STim.Szeto@Sun.COM 	}
1588*9585STim.Szeto@Sun.COM 
1589*9585STim.Szeto@Sun.COM 	/* Check logical unit provider name to call correct dtype function */
1590*9585STim.Szeto@Sun.COM 	if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps))
1591*9585STim.Szeto@Sun.COM 	    != STMF_STATUS_SUCCESS) {
1592*9585STim.Szeto@Sun.COM 		return (ret);
1593*9585STim.Szeto@Sun.COM 	} else {
1594*9585STim.Szeto@Sun.COM 		if (strcmp(luProps.providerName, "sbd") == 0) {
1595*9585STim.Szeto@Sun.COM 			ret = modifyDiskLuProp(luGuid, NULL, prop, propVal);
1596*9585STim.Szeto@Sun.COM 		} else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) {
1597*9585STim.Szeto@Sun.COM 			return (STMF_ERROR_NOT_FOUND);
1598*9585STim.Szeto@Sun.COM 		} else {
1599*9585STim.Szeto@Sun.COM 			return (STMF_ERROR_INVALID_ARG);
1600*9585STim.Szeto@Sun.COM 		}
1601*9585STim.Szeto@Sun.COM 	}
1602*9585STim.Szeto@Sun.COM 
1603*9585STim.Szeto@Sun.COM 	return (ret);
1604*9585STim.Szeto@Sun.COM }
1605*9585STim.Szeto@Sun.COM 
1606*9585STim.Szeto@Sun.COM /*
1607*9585STim.Szeto@Sun.COM  * stmfModifyLuByFname
1608*9585STim.Szeto@Sun.COM  *
1609*9585STim.Szeto@Sun.COM  * Purpose: Modify a device by filename. Device does not need to be registered.
1610*9585STim.Szeto@Sun.COM  *
1611*9585STim.Szeto@Sun.COM  * dType - type of device to modify
1612*9585STim.Szeto@Sun.COM  *         STMF_DISK
1613*9585STim.Szeto@Sun.COM  *
1614*9585STim.Szeto@Sun.COM  * fname - filename or meta filename
1615*9585STim.Szeto@Sun.COM  * prop - valid property identifier
1616*9585STim.Szeto@Sun.COM  * propVal - property value
1617*9585STim.Szeto@Sun.COM  *
1618*9585STim.Szeto@Sun.COM  */
1619*9585STim.Szeto@Sun.COM int
1620*9585STim.Szeto@Sun.COM stmfModifyLuByFname(uint16_t dType, const char *fname, uint32_t prop,
1621*9585STim.Szeto@Sun.COM     const char *propVal)
1622*9585STim.Szeto@Sun.COM {
1623*9585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
1624*9585STim.Szeto@Sun.COM 	if (fname == NULL) {
1625*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
1626*9585STim.Szeto@Sun.COM 	}
1627*9585STim.Szeto@Sun.COM 
1628*9585STim.Szeto@Sun.COM 	if (dType == STMF_DISK) {
1629*9585STim.Szeto@Sun.COM 		ret = modifyDiskLuProp(NULL, fname, prop, propVal);
1630*9585STim.Szeto@Sun.COM 	} else {
1631*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
1632*9585STim.Szeto@Sun.COM 	}
1633*9585STim.Szeto@Sun.COM 
1634*9585STim.Szeto@Sun.COM 	return (ret);
1635*9585STim.Szeto@Sun.COM }
1636*9585STim.Szeto@Sun.COM 
1637*9585STim.Szeto@Sun.COM static int
1638*9585STim.Szeto@Sun.COM modifyDiskLuProp(stmfGuid *luGuid, const char *fname, uint32_t prop,
1639*9585STim.Szeto@Sun.COM     const char *propVal)
1640*9585STim.Szeto@Sun.COM {
1641*9585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
1642*9585STim.Szeto@Sun.COM 	luResource hdl = NULL;
1643*9585STim.Szeto@Sun.COM 	luResourceImpl *luPropsHdl;
1644*9585STim.Szeto@Sun.COM 
1645*9585STim.Szeto@Sun.COM 	ret = stmfCreateLuResource(STMF_DISK, &hdl);
1646*9585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
1647*9585STim.Szeto@Sun.COM 		return (ret);
1648*9585STim.Szeto@Sun.COM 	}
1649*9585STim.Szeto@Sun.COM 	ret = validateModifyDiskProp(prop);
1650*9585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
1651*9585STim.Szeto@Sun.COM 		(void) stmfFreeLuResource(hdl);
1652*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_PROP);
1653*9585STim.Szeto@Sun.COM 	}
1654*9585STim.Szeto@Sun.COM 	ret = stmfSetLuProp(hdl, prop, propVal);
1655*9585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
1656*9585STim.Szeto@Sun.COM 		(void) stmfFreeLuResource(hdl);
1657*9585STim.Szeto@Sun.COM 		return (ret);
1658*9585STim.Szeto@Sun.COM 	}
1659*9585STim.Szeto@Sun.COM 	luPropsHdl = hdl;
1660*9585STim.Szeto@Sun.COM 	ret = modifyDiskLu((diskResource *)luPropsHdl->resource, luGuid, fname);
1661*9585STim.Szeto@Sun.COM 	(void) stmfFreeLuResource(hdl);
1662*9585STim.Szeto@Sun.COM 	return (ret);
1663*9585STim.Szeto@Sun.COM }
1664*9585STim.Szeto@Sun.COM 
1665*9585STim.Szeto@Sun.COM static int
1666*9585STim.Szeto@Sun.COM validateModifyDiskProp(uint32_t prop)
1667*9585STim.Szeto@Sun.COM {
1668*9585STim.Szeto@Sun.COM 	switch (prop) {
1669*9585STim.Szeto@Sun.COM 		case STMF_LU_PROP_ALIAS:
1670*9585STim.Szeto@Sun.COM 		case STMF_LU_PROP_SIZE:
1671*9585STim.Szeto@Sun.COM 		case STMF_LU_PROP_WRITE_PROTECT:
1672*9585STim.Szeto@Sun.COM 		case STMF_LU_PROP_WRITE_CACHE_DISABLE:
1673*9585STim.Szeto@Sun.COM 			return (STMF_STATUS_SUCCESS);
1674*9585STim.Szeto@Sun.COM 			break;
1675*9585STim.Szeto@Sun.COM 		default:
1676*9585STim.Szeto@Sun.COM 			return (STMF_STATUS_ERROR);
1677*9585STim.Szeto@Sun.COM 			break;
1678*9585STim.Szeto@Sun.COM 	}
1679*9585STim.Szeto@Sun.COM }
1680*9585STim.Szeto@Sun.COM 
1681*9585STim.Szeto@Sun.COM static int
1682*9585STim.Szeto@Sun.COM modifyDiskLu(diskResource *disk, stmfGuid *luGuid, const char *fname)
1683*9585STim.Szeto@Sun.COM {
1684*9585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
1685*9585STim.Szeto@Sun.COM 	int luAliasLen = 0;
1686*9585STim.Szeto@Sun.COM 	int mluBufSize = 0;
1687*9585STim.Szeto@Sun.COM 	int bufOffset = 0;
1688*9585STim.Szeto@Sun.COM 	int fd = 0;
1689*9585STim.Szeto@Sun.COM 	int ioctlRet;
1690*9585STim.Szeto@Sun.COM 	int savedErrno;
1691*9585STim.Szeto@Sun.COM 	int fnameSize = 0;
1692*9585STim.Szeto@Sun.COM 	stmf_iocdata_t sbdIoctl = {0};
1693*9585STim.Szeto@Sun.COM 
1694*9585STim.Szeto@Sun.COM 	sbd_modify_lu_t *sbdLu = NULL;
1695*9585STim.Szeto@Sun.COM 
1696*9585STim.Szeto@Sun.COM 	if (luGuid == NULL && fname == NULL) {
1697*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
1698*9585STim.Szeto@Sun.COM 	}
1699*9585STim.Szeto@Sun.COM 
1700*9585STim.Szeto@Sun.COM 	if (fname) {
1701*9585STim.Szeto@Sun.COM 		fnameSize = strlen(fname) + 1;
1702*9585STim.Szeto@Sun.COM 		mluBufSize += fnameSize;
1703*9585STim.Szeto@Sun.COM 	}
1704*9585STim.Szeto@Sun.COM 
1705*9585STim.Szeto@Sun.COM 	/*
1706*9585STim.Szeto@Sun.COM 	 * Open control node for sbd
1707*9585STim.Szeto@Sun.COM 	 */
1708*9585STim.Szeto@Sun.COM 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
1709*9585STim.Szeto@Sun.COM 		return (ret);
1710*9585STim.Szeto@Sun.COM 
1711*9585STim.Szeto@Sun.COM 	if (disk->luAliasValid) {
1712*9585STim.Szeto@Sun.COM 		luAliasLen = strlen(disk->luAlias);
1713*9585STim.Szeto@Sun.COM 		mluBufSize += luAliasLen + 1;
1714*9585STim.Szeto@Sun.COM 	}
1715*9585STim.Szeto@Sun.COM 
1716*9585STim.Szeto@Sun.COM 	/*
1717*9585STim.Szeto@Sun.COM 	 * 8 is the size of the buffer set aside for
1718*9585STim.Szeto@Sun.COM 	 * concatenation of variable length fields
1719*9585STim.Szeto@Sun.COM 	 */
1720*9585STim.Szeto@Sun.COM 	sbdLu = (sbd_modify_lu_t *)calloc(1,
1721*9585STim.Szeto@Sun.COM 	    sizeof (sbd_modify_lu_t) + mluBufSize - 8 + fnameSize);
1722*9585STim.Szeto@Sun.COM 	if (sbdLu == NULL) {
1723*9585STim.Szeto@Sun.COM 		(void) close(fd);
1724*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_NOMEM);
1725*9585STim.Szeto@Sun.COM 	}
1726*9585STim.Szeto@Sun.COM 
1727*9585STim.Szeto@Sun.COM 	sbdLu->mlu_struct_size = sizeof (sbd_modify_lu_t) +
1728*9585STim.Szeto@Sun.COM 	    mluBufSize - 8 + fnameSize;
1729*9585STim.Szeto@Sun.COM 
1730*9585STim.Szeto@Sun.COM 	if (disk->luAliasValid) {
1731*9585STim.Szeto@Sun.COM 		sbdLu->mlu_alias_valid = 1;
1732*9585STim.Szeto@Sun.COM 		sbdLu->mlu_alias_off = bufOffset;
1733*9585STim.Szeto@Sun.COM 		bcopy(disk->luAlias, &(sbdLu->mlu_buf[bufOffset]),
1734*9585STim.Szeto@Sun.COM 		    luAliasLen + 1);
1735*9585STim.Szeto@Sun.COM 		bufOffset += luAliasLen + 1;
1736*9585STim.Szeto@Sun.COM 	}
1737*9585STim.Szeto@Sun.COM 
1738*9585STim.Szeto@Sun.COM 	if (disk->luSizeValid) {
1739*9585STim.Szeto@Sun.COM 		sbdLu->mlu_lu_size_valid = 1;
1740*9585STim.Szeto@Sun.COM 		sbdLu->mlu_lu_size = disk->luSize;
1741*9585STim.Szeto@Sun.COM 	}
1742*9585STim.Szeto@Sun.COM 
1743*9585STim.Szeto@Sun.COM 	if (disk->writeProtectEnableValid) {
1744*9585STim.Szeto@Sun.COM 		sbdLu->mlu_write_protected_valid = 1;
1745*9585STim.Szeto@Sun.COM 		if (disk->writeProtectEnable) {
1746*9585STim.Szeto@Sun.COM 			sbdLu->mlu_write_protected = 1;
1747*9585STim.Szeto@Sun.COM 		}
1748*9585STim.Szeto@Sun.COM 	}
1749*9585STim.Szeto@Sun.COM 
1750*9585STim.Szeto@Sun.COM 	if (disk->writebackCacheDisableValid) {
1751*9585STim.Szeto@Sun.COM 		sbdLu->mlu_writeback_cache_disable_valid = 1;
1752*9585STim.Szeto@Sun.COM 		if (disk->writebackCacheDisable) {
1753*9585STim.Szeto@Sun.COM 			sbdLu->mlu_writeback_cache_disable = 1;
1754*9585STim.Szeto@Sun.COM 		}
1755*9585STim.Szeto@Sun.COM 	}
1756*9585STim.Szeto@Sun.COM 
1757*9585STim.Szeto@Sun.COM 	if (luGuid) {
1758*9585STim.Szeto@Sun.COM 		bcopy(luGuid, sbdLu->mlu_input_guid, sizeof (stmfGuid));
1759*9585STim.Szeto@Sun.COM 		sbdLu->mlu_by_guid = 1;
1760*9585STim.Szeto@Sun.COM 	} else {
1761*9585STim.Szeto@Sun.COM 		sbdLu->mlu_fname_off = bufOffset;
1762*9585STim.Szeto@Sun.COM 		bcopy(fname, &(sbdLu->mlu_buf[bufOffset]), fnameSize + 1);
1763*9585STim.Szeto@Sun.COM 		sbdLu->mlu_by_fname = 1;
1764*9585STim.Szeto@Sun.COM 	}
1765*9585STim.Szeto@Sun.COM 
1766*9585STim.Szeto@Sun.COM 	sbdIoctl.stmf_version = STMF_VERSION_1;
1767*9585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf_size = sbdLu->mlu_struct_size;
1768*9585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdLu;
1769*9585STim.Szeto@Sun.COM 
1770*9585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, SBD_IOCTL_MODIFY_LU, &sbdIoctl);
1771*9585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
1772*9585STim.Szeto@Sun.COM 		savedErrno = errno;
1773*9585STim.Szeto@Sun.COM 		switch (savedErrno) {
1774*9585STim.Szeto@Sun.COM 			case EBUSY:
1775*9585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
1776*9585STim.Szeto@Sun.COM 				break;
1777*9585STim.Szeto@Sun.COM 			case EPERM:
1778*9585STim.Szeto@Sun.COM 			case EACCES:
1779*9585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
1780*9585STim.Szeto@Sun.COM 				break;
1781*9585STim.Szeto@Sun.COM 			default:
1782*9585STim.Szeto@Sun.COM 				diskError(sbdIoctl.stmf_error, &ret);
1783*9585STim.Szeto@Sun.COM 				if (ret == STMF_STATUS_ERROR) {
1784*9585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
1785*9585STim.Szeto@Sun.COM 					"modifyDiskLu:ioctl "
1786*9585STim.Szeto@Sun.COM 					"error(%d) (%d) (%d)", ioctlRet,
1787*9585STim.Szeto@Sun.COM 					    sbdIoctl.stmf_error, savedErrno);
1788*9585STim.Szeto@Sun.COM 				}
1789*9585STim.Szeto@Sun.COM 				break;
1790*9585STim.Szeto@Sun.COM 		}
1791*9585STim.Szeto@Sun.COM 	}
1792*9585STim.Szeto@Sun.COM 
1793*9585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
1794*9585STim.Szeto@Sun.COM 		goto done;
1795*9585STim.Szeto@Sun.COM 	}
1796*9585STim.Szeto@Sun.COM 
1797*9585STim.Szeto@Sun.COM done:
1798*9585STim.Szeto@Sun.COM 	free(sbdLu);
1799*9585STim.Szeto@Sun.COM 	(void) close(fd);
1800*9585STim.Szeto@Sun.COM 	return (ret);
1801*9585STim.Szeto@Sun.COM }
1802*9585STim.Szeto@Sun.COM 
1803*9585STim.Szeto@Sun.COM /*
1804*9585STim.Szeto@Sun.COM  * removeGuidFromDiskStore
1805*9585STim.Szeto@Sun.COM  *
1806*9585STim.Szeto@Sun.COM  * Purpose: delete a logical unit from the sbd provider data
1807*9585STim.Szeto@Sun.COM  */
1808*9585STim.Szeto@Sun.COM static int
1809*9585STim.Szeto@Sun.COM removeGuidFromDiskStore(stmfGuid *guid)
1810*9585STim.Szeto@Sun.COM {
1811*9585STim.Szeto@Sun.COM 	return (persistDiskGuid(guid, NULL, B_FALSE));
1812*9585STim.Szeto@Sun.COM }
1813*9585STim.Szeto@Sun.COM 
1814*9585STim.Szeto@Sun.COM 
1815*9585STim.Szeto@Sun.COM /*
1816*9585STim.Szeto@Sun.COM  * addGuidToDiskStore
1817*9585STim.Szeto@Sun.COM  *
1818*9585STim.Szeto@Sun.COM  * Purpose: add a logical unit to the sbd provider data
1819*9585STim.Szeto@Sun.COM  */
1820*9585STim.Szeto@Sun.COM static int
1821*9585STim.Szeto@Sun.COM addGuidToDiskStore(stmfGuid *guid, char *filename)
1822*9585STim.Szeto@Sun.COM {
1823*9585STim.Szeto@Sun.COM 	return (persistDiskGuid(guid, filename, B_TRUE));
1824*9585STim.Szeto@Sun.COM }
1825*9585STim.Szeto@Sun.COM 
1826*9585STim.Szeto@Sun.COM 
1827*9585STim.Szeto@Sun.COM /*
1828*9585STim.Szeto@Sun.COM  * persistDiskGuid
1829*9585STim.Szeto@Sun.COM  *
1830*9585STim.Szeto@Sun.COM  * Purpose: Persist or unpersist a guid for the sbd provider data
1831*9585STim.Szeto@Sun.COM  *
1832*9585STim.Szeto@Sun.COM  */
1833*9585STim.Szeto@Sun.COM static int
1834*9585STim.Szeto@Sun.COM persistDiskGuid(stmfGuid *guid, char *filename, boolean_t persist)
1835*9585STim.Szeto@Sun.COM {
1836*9585STim.Szeto@Sun.COM 	char	    guidAsciiBuf[LU_ASCII_GUID_SIZE + 1] = {0};
1837*9585STim.Szeto@Sun.COM 	nvlist_t    *nvl = NULL;
1838*9585STim.Szeto@Sun.COM 
1839*9585STim.Szeto@Sun.COM 	uint64_t    setToken;
1840*9585STim.Szeto@Sun.COM 	boolean_t   retryGetProviderData = B_FALSE;
1841*9585STim.Szeto@Sun.COM 	boolean_t   newData = B_FALSE;
1842*9585STim.Szeto@Sun.COM 	int	    ret = STMF_STATUS_SUCCESS;
1843*9585STim.Szeto@Sun.COM 	int	    retryCnt = 0;
1844*9585STim.Szeto@Sun.COM 	int	    stmfRet;
1845*9585STim.Szeto@Sun.COM 
1846*9585STim.Szeto@Sun.COM 	/* if we're persisting a guid, there must be a filename */
1847*9585STim.Szeto@Sun.COM 	if (persist && !filename) {
1848*9585STim.Szeto@Sun.COM 		return (1);
1849*9585STim.Szeto@Sun.COM 	}
1850*9585STim.Szeto@Sun.COM 
1851*9585STim.Szeto@Sun.COM 	/* guid is stored in lowercase ascii hex */
1852*9585STim.Szeto@Sun.COM 	(void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf),
1853*9585STim.Szeto@Sun.COM 	    "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
1854*9585STim.Szeto@Sun.COM 	    "%02x%02x%02x%02x%02x%02x",
1855*9585STim.Szeto@Sun.COM 	    guid->guid[0], guid->guid[1], guid->guid[2], guid->guid[3],
1856*9585STim.Szeto@Sun.COM 	    guid->guid[4], guid->guid[5], guid->guid[6], guid->guid[7],
1857*9585STim.Szeto@Sun.COM 	    guid->guid[8], guid->guid[9], guid->guid[10], guid->guid[11],
1858*9585STim.Szeto@Sun.COM 	    guid->guid[12], guid->guid[13], guid->guid[14], guid->guid[15]);
1859*9585STim.Szeto@Sun.COM 
1860*9585STim.Szeto@Sun.COM 
1861*9585STim.Szeto@Sun.COM 	do {
1862*9585STim.Szeto@Sun.COM 		retryGetProviderData = B_FALSE;
1863*9585STim.Szeto@Sun.COM 		stmfRet = stmfGetProviderDataProt("sbd", &nvl,
1864*9585STim.Szeto@Sun.COM 		    STMF_LU_PROVIDER_TYPE, &setToken);
1865*9585STim.Szeto@Sun.COM 		if (stmfRet != STMF_STATUS_SUCCESS) {
1866*9585STim.Szeto@Sun.COM 			if (persist && stmfRet == STMF_ERROR_NOT_FOUND) {
1867*9585STim.Szeto@Sun.COM 				ret = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0);
1868*9585STim.Szeto@Sun.COM 				if (ret != 0) {
1869*9585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
1870*9585STim.Szeto@Sun.COM 					    "unpersistGuid:nvlist_alloc(%d)",
1871*9585STim.Szeto@Sun.COM 					    ret);
1872*9585STim.Szeto@Sun.COM 					ret = STMF_STATUS_ERROR;
1873*9585STim.Szeto@Sun.COM 					goto done;
1874*9585STim.Szeto@Sun.COM 				}
1875*9585STim.Szeto@Sun.COM 				newData = B_TRUE;
1876*9585STim.Szeto@Sun.COM 			} else {
1877*9585STim.Szeto@Sun.COM 				ret = stmfRet;
1878*9585STim.Szeto@Sun.COM 				goto done;
1879*9585STim.Szeto@Sun.COM 			}
1880*9585STim.Szeto@Sun.COM 		}
1881*9585STim.Szeto@Sun.COM 		if (persist) {
1882*9585STim.Szeto@Sun.COM 			ret = nvlist_add_string(nvl, guidAsciiBuf, filename);
1883*9585STim.Szeto@Sun.COM 		} else {
1884*9585STim.Szeto@Sun.COM 			ret = nvlist_remove(nvl, guidAsciiBuf,
1885*9585STim.Szeto@Sun.COM 			    DATA_TYPE_STRING);
1886*9585STim.Szeto@Sun.COM 			if (ret == ENOENT) {
1887*9585STim.Szeto@Sun.COM 				ret = 0;
1888*9585STim.Szeto@Sun.COM 			}
1889*9585STim.Szeto@Sun.COM 		}
1890*9585STim.Szeto@Sun.COM 		if (ret == 0) {
1891*9585STim.Szeto@Sun.COM 			if (newData) {
1892*9585STim.Szeto@Sun.COM 				stmfRet = stmfSetProviderDataProt("sbd", nvl,
1893*9585STim.Szeto@Sun.COM 				    STMF_LU_PROVIDER_TYPE, NULL);
1894*9585STim.Szeto@Sun.COM 			} else {
1895*9585STim.Szeto@Sun.COM 				stmfRet = stmfSetProviderDataProt("sbd", nvl,
1896*9585STim.Szeto@Sun.COM 				    STMF_LU_PROVIDER_TYPE, &setToken);
1897*9585STim.Szeto@Sun.COM 			}
1898*9585STim.Szeto@Sun.COM 			if (stmfRet != STMF_STATUS_SUCCESS) {
1899*9585STim.Szeto@Sun.COM 				if (stmfRet == STMF_ERROR_BUSY) {
1900*9585STim.Szeto@Sun.COM 					/* get/set failed, try again */
1901*9585STim.Szeto@Sun.COM 					retryGetProviderData = B_TRUE;
1902*9585STim.Szeto@Sun.COM 					if (retryCnt++ > MAX_PROVIDER_RETRY) {
1903*9585STim.Szeto@Sun.COM 						ret = stmfRet;
1904*9585STim.Szeto@Sun.COM 						break;
1905*9585STim.Szeto@Sun.COM 					}
1906*9585STim.Szeto@Sun.COM 					continue;
1907*9585STim.Szeto@Sun.COM 				} else if (stmfRet ==
1908*9585STim.Szeto@Sun.COM 				    STMF_ERROR_PROV_DATA_STALE) {
1909*9585STim.Szeto@Sun.COM 					/* update failed, try again */
1910*9585STim.Szeto@Sun.COM 					nvlist_free(nvl);
1911*9585STim.Szeto@Sun.COM 					nvl = NULL;
1912*9585STim.Szeto@Sun.COM 					retryGetProviderData = B_TRUE;
1913*9585STim.Szeto@Sun.COM 					if (retryCnt++ > MAX_PROVIDER_RETRY) {
1914*9585STim.Szeto@Sun.COM 						ret = stmfRet;
1915*9585STim.Szeto@Sun.COM 						break;
1916*9585STim.Szeto@Sun.COM 					}
1917*9585STim.Szeto@Sun.COM 					continue;
1918*9585STim.Szeto@Sun.COM 				} else {
1919*9585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
1920*9585STim.Szeto@Sun.COM 					    "unpersistGuid:error(%x)", stmfRet);
1921*9585STim.Szeto@Sun.COM 					ret = stmfRet;
1922*9585STim.Szeto@Sun.COM 				}
1923*9585STim.Szeto@Sun.COM 				break;
1924*9585STim.Szeto@Sun.COM 			}
1925*9585STim.Szeto@Sun.COM 		} else {
1926*9585STim.Szeto@Sun.COM 			syslog(LOG_DEBUG,
1927*9585STim.Szeto@Sun.COM 			    "unpersistGuid:error nvlist_add/remove(%d)",
1928*9585STim.Szeto@Sun.COM 			    ret);
1929*9585STim.Szeto@Sun.COM 			ret = STMF_STATUS_ERROR;
1930*9585STim.Szeto@Sun.COM 		}
1931*9585STim.Szeto@Sun.COM 	} while (retryGetProviderData);
1932*9585STim.Szeto@Sun.COM 
1933*9585STim.Szeto@Sun.COM done:
1934*9585STim.Szeto@Sun.COM 	nvlist_free(nvl);
1935*9585STim.Szeto@Sun.COM 	return (ret);
1936*9585STim.Szeto@Sun.COM }
1937*9585STim.Szeto@Sun.COM 
1938*9585STim.Szeto@Sun.COM 
1939*9585STim.Szeto@Sun.COM /*
1940*9585STim.Szeto@Sun.COM  * stmfGetLuProp
1941*9585STim.Szeto@Sun.COM  *
1942*9585STim.Szeto@Sun.COM  * Purpose: Get current value for a resource property
1943*9585STim.Szeto@Sun.COM  *
1944*9585STim.Szeto@Sun.COM  * hdl - luResource from a previous call to stmfCreateLuResource
1945*9585STim.Szeto@Sun.COM  *
1946*9585STim.Szeto@Sun.COM  * resourceProp - a valid resource property type
1947*9585STim.Szeto@Sun.COM  *
1948*9585STim.Szeto@Sun.COM  * propVal - void pointer to a pointer of the value to be retrieved
1949*9585STim.Szeto@Sun.COM  */
1950*9585STim.Szeto@Sun.COM int
1951*9585STim.Szeto@Sun.COM stmfGetLuProp(luResource hdl, uint32_t prop, char *propVal, size_t *propLen)
1952*9585STim.Szeto@Sun.COM {
1953*9585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
1954*9585STim.Szeto@Sun.COM 	luResourceImpl *luPropsHdl = hdl;
1955*9585STim.Szeto@Sun.COM 	if (hdl == NULL || propLen == NULL || propVal == NULL) {
1956*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
1957*9585STim.Szeto@Sun.COM 	}
1958*9585STim.Szeto@Sun.COM 
1959*9585STim.Szeto@Sun.COM 	if (luPropsHdl->type == STMF_DISK) {
1960*9585STim.Szeto@Sun.COM 		ret = getDiskProp(luPropsHdl, prop, propVal, propLen);
1961*9585STim.Szeto@Sun.COM 	} else {
1962*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
1963*9585STim.Szeto@Sun.COM 	}
1964*9585STim.Szeto@Sun.COM 
1965*9585STim.Szeto@Sun.COM 	return (ret);
1966*9585STim.Szeto@Sun.COM }
1967*9585STim.Szeto@Sun.COM 
1968*9585STim.Szeto@Sun.COM /*
1969*9585STim.Szeto@Sun.COM  * stmfGetLuResource
1970*9585STim.Szeto@Sun.COM  *
1971*9585STim.Szeto@Sun.COM  * Purpose: Get a logical unit resource handle for a given logical unit.
1972*9585STim.Szeto@Sun.COM  *
1973*9585STim.Szeto@Sun.COM  * hdl - pointer to luResource
1974*9585STim.Szeto@Sun.COM  */
1975*9585STim.Szeto@Sun.COM int
1976*9585STim.Szeto@Sun.COM stmfGetLuResource(stmfGuid *luGuid, luResource *hdl)
1977*9585STim.Szeto@Sun.COM {
1978*9585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
1979*9585STim.Szeto@Sun.COM 	stmfLogicalUnitProperties luProps;
1980*9585STim.Szeto@Sun.COM 
1981*9585STim.Szeto@Sun.COM 
1982*9585STim.Szeto@Sun.COM 	/* Check logical unit provider name to call correct dtype function */
1983*9585STim.Szeto@Sun.COM 	if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps))
1984*9585STim.Szeto@Sun.COM 	    != STMF_STATUS_SUCCESS) {
1985*9585STim.Szeto@Sun.COM 		return (ret);
1986*9585STim.Szeto@Sun.COM 	} else {
1987*9585STim.Szeto@Sun.COM 		if (strcmp(luProps.providerName, "sbd") == 0) {
1988*9585STim.Szeto@Sun.COM 			ret = getDiskAllProps(luGuid, hdl);
1989*9585STim.Szeto@Sun.COM 		} else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) {
1990*9585STim.Szeto@Sun.COM 			return (STMF_ERROR_NOT_FOUND);
1991*9585STim.Szeto@Sun.COM 		} else {
1992*9585STim.Szeto@Sun.COM 			return (STMF_ERROR_INVALID_ARG);
1993*9585STim.Szeto@Sun.COM 		}
1994*9585STim.Szeto@Sun.COM 	}
1995*9585STim.Szeto@Sun.COM 
1996*9585STim.Szeto@Sun.COM 	return (ret);
1997*9585STim.Szeto@Sun.COM }
1998*9585STim.Szeto@Sun.COM 
1999*9585STim.Szeto@Sun.COM /*
2000*9585STim.Szeto@Sun.COM  * getDiskAllProps
2001*9585STim.Szeto@Sun.COM  *
2002*9585STim.Szeto@Sun.COM  * Purpose: load all disk properties from sbd driver
2003*9585STim.Szeto@Sun.COM  *
2004*9585STim.Szeto@Sun.COM  * luGuid - guid of disk device for which properties are to be retrieved
2005*9585STim.Szeto@Sun.COM  * hdl - allocated luResource into which properties are to be copied
2006*9585STim.Szeto@Sun.COM  *
2007*9585STim.Szeto@Sun.COM  */
2008*9585STim.Szeto@Sun.COM static int
2009*9585STim.Szeto@Sun.COM getDiskAllProps(stmfGuid *luGuid, luResource *hdl)
2010*9585STim.Szeto@Sun.COM {
2011*9585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
2012*9585STim.Szeto@Sun.COM 	int fd;
2013*9585STim.Szeto@Sun.COM 	sbd_lu_props_t *sbdProps;
2014*9585STim.Szeto@Sun.COM 	int ioctlRet;
2015*9585STim.Szeto@Sun.COM 	int savedErrno;
2016*9585STim.Szeto@Sun.COM 	int sbdPropsSize = sizeof (*sbdProps) + MAX_SBD_PROPS;
2017*9585STim.Szeto@Sun.COM 	stmf_iocdata_t sbdIoctl = {0};
2018*9585STim.Szeto@Sun.COM 
2019*9585STim.Szeto@Sun.COM 	/*
2020*9585STim.Szeto@Sun.COM 	 * Open control node for sbd
2021*9585STim.Szeto@Sun.COM 	 */
2022*9585STim.Szeto@Sun.COM 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
2023*9585STim.Szeto@Sun.COM 		return (ret);
2024*9585STim.Szeto@Sun.COM 
2025*9585STim.Szeto@Sun.COM 
2026*9585STim.Szeto@Sun.COM 	*hdl = calloc(1, sizeof (luResourceImpl));
2027*9585STim.Szeto@Sun.COM 	if (*hdl == NULL) {
2028*9585STim.Szeto@Sun.COM 		(void) close(fd);
2029*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_NOMEM);
2030*9585STim.Szeto@Sun.COM 	}
2031*9585STim.Szeto@Sun.COM 
2032*9585STim.Szeto@Sun.COM 	sbdProps = calloc(1, sbdPropsSize);
2033*9585STim.Szeto@Sun.COM 	if (sbdProps == NULL) {
2034*9585STim.Szeto@Sun.COM 		free(*hdl);
2035*9585STim.Szeto@Sun.COM 		(void) close(fd);
2036*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_NOMEM);
2037*9585STim.Szeto@Sun.COM 	}
2038*9585STim.Szeto@Sun.COM 
2039*9585STim.Szeto@Sun.COM 	ret = createDiskResource((luResourceImpl *)*hdl);
2040*9585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
2041*9585STim.Szeto@Sun.COM 		free(*hdl);
2042*9585STim.Szeto@Sun.COM 		(void) close(fd);
2043*9585STim.Szeto@Sun.COM 		return (ret);
2044*9585STim.Szeto@Sun.COM 	}
2045*9585STim.Szeto@Sun.COM 
2046*9585STim.Szeto@Sun.COM 	sbdProps->slp_input_guid = 1;
2047*9585STim.Szeto@Sun.COM 	bcopy(luGuid, sbdProps->slp_guid, sizeof (sbdProps->slp_guid));
2048*9585STim.Szeto@Sun.COM 
2049*9585STim.Szeto@Sun.COM 	sbdIoctl.stmf_version = STMF_VERSION_1;
2050*9585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf_size = sbdPropsSize;
2051*9585STim.Szeto@Sun.COM 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdProps;
2052*9585STim.Szeto@Sun.COM 	sbdIoctl.stmf_obuf_size = sbdPropsSize;
2053*9585STim.Szeto@Sun.COM 	sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdProps;
2054*9585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, SBD_IOCTL_GET_LU_PROPS, &sbdIoctl);
2055*9585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
2056*9585STim.Szeto@Sun.COM 		savedErrno = errno;
2057*9585STim.Szeto@Sun.COM 		switch (savedErrno) {
2058*9585STim.Szeto@Sun.COM 			case EBUSY:
2059*9585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
2060*9585STim.Szeto@Sun.COM 				break;
2061*9585STim.Szeto@Sun.COM 			case EPERM:
2062*9585STim.Szeto@Sun.COM 			case EACCES:
2063*9585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
2064*9585STim.Szeto@Sun.COM 				break;
2065*9585STim.Szeto@Sun.COM 			case ENOENT:
2066*9585STim.Szeto@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
2067*9585STim.Szeto@Sun.COM 				break;
2068*9585STim.Szeto@Sun.COM 			default:
2069*9585STim.Szeto@Sun.COM 				syslog(LOG_DEBUG,
2070*9585STim.Szeto@Sun.COM 				    "getDiskAllProps:ioctl error(%d) (%d) (%d)",
2071*9585STim.Szeto@Sun.COM 				    ioctlRet, sbdIoctl.stmf_error, savedErrno);
2072*9585STim.Szeto@Sun.COM 				ret = STMF_STATUS_ERROR;
2073*9585STim.Szeto@Sun.COM 				break;
2074*9585STim.Szeto@Sun.COM 		}
2075*9585STim.Szeto@Sun.COM 	}
2076*9585STim.Szeto@Sun.COM 
2077*9585STim.Szeto@Sun.COM 	if (ret == STMF_STATUS_SUCCESS) {
2078*9585STim.Szeto@Sun.COM 		ret = loadDiskPropsFromDriver((luResourceImpl *)*hdl, sbdProps);
2079*9585STim.Szeto@Sun.COM 	}
2080*9585STim.Szeto@Sun.COM 
2081*9585STim.Szeto@Sun.COM 	(void) close(fd);
2082*9585STim.Szeto@Sun.COM 	return (ret);
2083*9585STim.Szeto@Sun.COM }
2084*9585STim.Szeto@Sun.COM 
2085*9585STim.Szeto@Sun.COM /*
2086*9585STim.Szeto@Sun.COM  * loadDiskPropsFromDriver
2087*9585STim.Szeto@Sun.COM  *
2088*9585STim.Szeto@Sun.COM  * Purpose: Retrieve all disk type properties from sbd driver
2089*9585STim.Szeto@Sun.COM  *
2090*9585STim.Szeto@Sun.COM  * hdl - Allocated luResourceImpl
2091*9585STim.Szeto@Sun.COM  * sbdProps - sbd_lu_props_t structure returned from sbd driver
2092*9585STim.Szeto@Sun.COM  *
2093*9585STim.Szeto@Sun.COM  */
2094*9585STim.Szeto@Sun.COM static int
2095*9585STim.Szeto@Sun.COM loadDiskPropsFromDriver(luResourceImpl *hdl, sbd_lu_props_t *sbdProps)
2096*9585STim.Szeto@Sun.COM {
2097*9585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
2098*9585STim.Szeto@Sun.COM 	diskResource *diskLu = hdl->resource;
2099*9585STim.Szeto@Sun.COM 	/* copy guid */
2100*9585STim.Szeto@Sun.COM 	diskLu->luGuidValid = B_TRUE;
2101*9585STim.Szeto@Sun.COM 	bcopy(sbdProps->slp_guid, diskLu->luGuid, sizeof (sbdProps->slp_guid));
2102*9585STim.Szeto@Sun.COM 
2103*9585STim.Szeto@Sun.COM 	if (sbdProps->slp_separate_meta && sbdProps->slp_meta_fname_valid) {
2104*9585STim.Szeto@Sun.COM 		diskLu->luMetaFileNameValid = B_TRUE;
2105*9585STim.Szeto@Sun.COM 		if (strlcpy(diskLu->luMetaFileName,
2106*9585STim.Szeto@Sun.COM 		    (char *)&(sbdProps->slp_buf[sbdProps->slp_meta_fname_off]),
2107*9585STim.Szeto@Sun.COM 		    sizeof (diskLu->luMetaFileName)) >=
2108*9585STim.Szeto@Sun.COM 		    sizeof (diskLu->luMetaFileName)) {
2109*9585STim.Szeto@Sun.COM 			return (STMF_STATUS_ERROR);
2110*9585STim.Szeto@Sun.COM 		}
2111*9585STim.Szeto@Sun.COM 	}
2112*9585STim.Szeto@Sun.COM 
2113*9585STim.Szeto@Sun.COM 	if (sbdProps->slp_data_fname_valid) {
2114*9585STim.Szeto@Sun.COM 		diskLu->luDataFileNameValid = B_TRUE;
2115*9585STim.Szeto@Sun.COM 		if (strlcpy(diskLu->luDataFileName,
2116*9585STim.Szeto@Sun.COM 		    (char *)&(sbdProps->slp_buf[sbdProps->slp_data_fname_off]),
2117*9585STim.Szeto@Sun.COM 		    sizeof (diskLu->luDataFileName)) >=
2118*9585STim.Szeto@Sun.COM 		    sizeof (diskLu->luDataFileName)) {
2119*9585STim.Szeto@Sun.COM 			return (STMF_STATUS_ERROR);
2120*9585STim.Szeto@Sun.COM 		}
2121*9585STim.Szeto@Sun.COM 	}
2122*9585STim.Szeto@Sun.COM 
2123*9585STim.Szeto@Sun.COM 	if (sbdProps->slp_serial_valid) {
2124*9585STim.Szeto@Sun.COM 		diskLu->serialNumValid = B_TRUE;
2125*9585STim.Szeto@Sun.COM 		bcopy(&(sbdProps->slp_buf[sbdProps->slp_serial_off]),
2126*9585STim.Szeto@Sun.COM 		    diskLu->serialNum, sbdProps->slp_serial_size);
2127*9585STim.Szeto@Sun.COM 	}
2128*9585STim.Szeto@Sun.COM 
2129*9585STim.Szeto@Sun.COM 	if (sbdProps->slp_alias_valid) {
2130*9585STim.Szeto@Sun.COM 		diskLu->luAliasValid = B_TRUE;
2131*9585STim.Szeto@Sun.COM 		if (strlcpy(diskLu->luAlias,
2132*9585STim.Szeto@Sun.COM 		    (char *)&(sbdProps->slp_buf[sbdProps->slp_alias_off]),
2133*9585STim.Szeto@Sun.COM 		    sizeof (diskLu->luAlias)) >=
2134*9585STim.Szeto@Sun.COM 		    sizeof (diskLu->luAlias)) {
2135*9585STim.Szeto@Sun.COM 			return (STMF_STATUS_ERROR);
2136*9585STim.Szeto@Sun.COM 		}
2137*9585STim.Szeto@Sun.COM 	} else { /* set alias to data filename if not set */
2138*9585STim.Szeto@Sun.COM 		if (sbdProps->slp_data_fname_valid) {
2139*9585STim.Szeto@Sun.COM 			diskLu->luAliasValid = B_TRUE;
2140*9585STim.Szeto@Sun.COM 			if (strlcpy(diskLu->luAlias,
2141*9585STim.Szeto@Sun.COM 			    (char *)&(sbdProps->slp_buf[
2142*9585STim.Szeto@Sun.COM 			    sbdProps->slp_data_fname_off]),
2143*9585STim.Szeto@Sun.COM 			    sizeof (diskLu->luAlias)) >=
2144*9585STim.Szeto@Sun.COM 			    sizeof (diskLu->luAlias)) {
2145*9585STim.Szeto@Sun.COM 				return (STMF_STATUS_ERROR);
2146*9585STim.Szeto@Sun.COM 			}
2147*9585STim.Szeto@Sun.COM 		}
2148*9585STim.Szeto@Sun.COM 	}
2149*9585STim.Szeto@Sun.COM 
2150*9585STim.Szeto@Sun.COM 	diskLu->vidValid = B_TRUE;
2151*9585STim.Szeto@Sun.COM 	bcopy(sbdProps->slp_vid, diskLu->vid, sizeof (diskLu->vid));
2152*9585STim.Szeto@Sun.COM 
2153*9585STim.Szeto@Sun.COM 	diskLu->pidValid = B_TRUE;
2154*9585STim.Szeto@Sun.COM 	bcopy(sbdProps->slp_pid, diskLu->pid, sizeof (diskLu->pid));
2155*9585STim.Szeto@Sun.COM 
2156*9585STim.Szeto@Sun.COM 	diskLu->revValid = B_TRUE;
2157*9585STim.Szeto@Sun.COM 	bcopy(sbdProps->slp_rev, diskLu->rev, sizeof (diskLu->rev));
2158*9585STim.Szeto@Sun.COM 
2159*9585STim.Szeto@Sun.COM 	diskLu->writeProtectEnableValid = B_TRUE;
2160*9585STim.Szeto@Sun.COM 	if (sbdProps->slp_write_protected) {
2161*9585STim.Szeto@Sun.COM 		diskLu->writeProtectEnable = B_TRUE;
2162*9585STim.Szeto@Sun.COM 	}
2163*9585STim.Szeto@Sun.COM 
2164*9585STim.Szeto@Sun.COM 	diskLu->writebackCacheDisableValid = B_TRUE;
2165*9585STim.Szeto@Sun.COM 	if (sbdProps->slp_writeback_cache_disable_cur) {
2166*9585STim.Szeto@Sun.COM 		diskLu->writebackCacheDisable = B_TRUE;
2167*9585STim.Szeto@Sun.COM 	}
2168*9585STim.Szeto@Sun.COM 
2169*9585STim.Szeto@Sun.COM 	diskLu->blkSizeValid = B_TRUE;
2170*9585STim.Szeto@Sun.COM 	diskLu->blkSize = sbdProps->slp_blksize;
2171*9585STim.Szeto@Sun.COM 
2172*9585STim.Szeto@Sun.COM 	diskLu->luSizeValid = B_TRUE;
2173*9585STim.Szeto@Sun.COM 	diskLu->luSize = sbdProps->slp_lu_size;
2174*9585STim.Szeto@Sun.COM 
2175*9585STim.Szeto@Sun.COM 	return (ret);
2176*9585STim.Szeto@Sun.COM }
2177*9585STim.Szeto@Sun.COM 
2178*9585STim.Szeto@Sun.COM 
2179*9585STim.Szeto@Sun.COM /*
2180*9585STim.Szeto@Sun.COM  * stmfSetLuProp
2181*9585STim.Szeto@Sun.COM  *
2182*9585STim.Szeto@Sun.COM  * Purpose: set a property on an luResource
2183*9585STim.Szeto@Sun.COM  *
2184*9585STim.Szeto@Sun.COM  * hdl - allocated luResource
2185*9585STim.Szeto@Sun.COM  * prop - property identifier
2186*9585STim.Szeto@Sun.COM  * propVal - property value to be set
2187*9585STim.Szeto@Sun.COM  */
2188*9585STim.Szeto@Sun.COM int
2189*9585STim.Szeto@Sun.COM stmfSetLuProp(luResource hdl, uint32_t prop, const char *propVal)
2190*9585STim.Szeto@Sun.COM {
2191*9585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
2192*9585STim.Szeto@Sun.COM 	luResourceImpl *luPropsHdl = hdl;
2193*9585STim.Szeto@Sun.COM 	if (hdl == NULL) {
2194*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
2195*9585STim.Szeto@Sun.COM 	}
2196*9585STim.Szeto@Sun.COM 
2197*9585STim.Szeto@Sun.COM 	if (luPropsHdl->type == STMF_DISK) {
2198*9585STim.Szeto@Sun.COM 		ret = setDiskProp(luPropsHdl, prop, propVal);
2199*9585STim.Szeto@Sun.COM 	} else {
2200*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
2201*9585STim.Szeto@Sun.COM 	}
2202*9585STim.Szeto@Sun.COM 
2203*9585STim.Szeto@Sun.COM 	return (ret);
2204*9585STim.Szeto@Sun.COM }
2205*9585STim.Szeto@Sun.COM 
2206*9585STim.Szeto@Sun.COM /*
2207*9585STim.Szeto@Sun.COM  * getDiskProp
2208*9585STim.Szeto@Sun.COM  *
2209*9585STim.Szeto@Sun.COM  * Purpose: retrieve a given property from a logical unit resource of type disk
2210*9585STim.Szeto@Sun.COM  *
2211*9585STim.Szeto@Sun.COM  * hdl - allocated luResourceImpl
2212*9585STim.Szeto@Sun.COM  * prop - property identifier
2213*9585STim.Szeto@Sun.COM  * propVal - pointer to character to contain the retrieved property value
2214*9585STim.Szeto@Sun.COM  * propLen - On input this is the length of propVal. On failure, it contains the
2215*9585STim.Szeto@Sun.COM  *           number of bytes required for propVal
2216*9585STim.Szeto@Sun.COM  */
2217*9585STim.Szeto@Sun.COM static int
2218*9585STim.Szeto@Sun.COM getDiskProp(luResourceImpl *hdl, uint32_t prop, char *propVal, size_t *propLen)
2219*9585STim.Szeto@Sun.COM {
2220*9585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
2221*9585STim.Szeto@Sun.COM 	diskResource *diskLu = hdl->resource;
2222*9585STim.Szeto@Sun.COM 	size_t reqLen;
2223*9585STim.Szeto@Sun.COM 
2224*9585STim.Szeto@Sun.COM 	switch (prop) {
2225*9585STim.Szeto@Sun.COM 		case STMF_LU_PROP_BLOCK_SIZE:
2226*9585STim.Szeto@Sun.COM 			if (diskLu->blkSizeValid == B_FALSE) {
2227*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
2228*9585STim.Szeto@Sun.COM 			}
2229*9585STim.Szeto@Sun.COM 			reqLen = snprintf(propVal, *propLen, "%llu",
2230*9585STim.Szeto@Sun.COM 			    (u_longlong_t)diskLu->blkSize);
2231*9585STim.Szeto@Sun.COM 			if (reqLen >= *propLen) {
2232*9585STim.Szeto@Sun.COM 				*propLen = reqLen + 1;
2233*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
2234*9585STim.Szeto@Sun.COM 			}
2235*9585STim.Szeto@Sun.COM 			break;
2236*9585STim.Szeto@Sun.COM 		case STMF_LU_PROP_FILENAME:
2237*9585STim.Szeto@Sun.COM 			if (diskLu->luDataFileNameValid == B_FALSE) {
2238*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
2239*9585STim.Szeto@Sun.COM 			}
2240*9585STim.Szeto@Sun.COM 			if ((reqLen = strlcpy(propVal, diskLu->luDataFileName,
2241*9585STim.Szeto@Sun.COM 			    *propLen)) >= *propLen) {
2242*9585STim.Szeto@Sun.COM 				*propLen = reqLen + 1;
2243*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
2244*9585STim.Szeto@Sun.COM 			}
2245*9585STim.Szeto@Sun.COM 			break;
2246*9585STim.Szeto@Sun.COM 		case STMF_LU_PROP_META_FILENAME:
2247*9585STim.Szeto@Sun.COM 			if (diskLu->luMetaFileNameValid == B_FALSE) {
2248*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
2249*9585STim.Szeto@Sun.COM 			}
2250*9585STim.Szeto@Sun.COM 			if ((reqLen = strlcpy(propVal, diskLu->luMetaFileName,
2251*9585STim.Szeto@Sun.COM 			    *propLen)) >= *propLen) {
2252*9585STim.Szeto@Sun.COM 				*propLen = reqLen + 1;
2253*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
2254*9585STim.Szeto@Sun.COM 			}
2255*9585STim.Szeto@Sun.COM 			break;
2256*9585STim.Szeto@Sun.COM 		case STMF_LU_PROP_GUID:
2257*9585STim.Szeto@Sun.COM 			if (diskLu->luGuidValid == B_FALSE) {
2258*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
2259*9585STim.Szeto@Sun.COM 			}
2260*9585STim.Szeto@Sun.COM 			reqLen = snprintf(propVal, *propLen,
2261*9585STim.Szeto@Sun.COM 			    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X"
2262*9585STim.Szeto@Sun.COM 			    "%02X%02X%02X%02X",
2263*9585STim.Szeto@Sun.COM 			    diskLu->luGuid[0], diskLu->luGuid[1],
2264*9585STim.Szeto@Sun.COM 			    diskLu->luGuid[2], diskLu->luGuid[3],
2265*9585STim.Szeto@Sun.COM 			    diskLu->luGuid[4], diskLu->luGuid[5],
2266*9585STim.Szeto@Sun.COM 			    diskLu->luGuid[6], diskLu->luGuid[7],
2267*9585STim.Szeto@Sun.COM 			    diskLu->luGuid[8], diskLu->luGuid[9],
2268*9585STim.Szeto@Sun.COM 			    diskLu->luGuid[10], diskLu->luGuid[11],
2269*9585STim.Szeto@Sun.COM 			    diskLu->luGuid[12], diskLu->luGuid[13],
2270*9585STim.Szeto@Sun.COM 			    diskLu->luGuid[14], diskLu->luGuid[15]);
2271*9585STim.Szeto@Sun.COM 			if (reqLen >= *propLen) {
2272*9585STim.Szeto@Sun.COM 				*propLen = reqLen + 1;
2273*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
2274*9585STim.Szeto@Sun.COM 			}
2275*9585STim.Szeto@Sun.COM 			break;
2276*9585STim.Szeto@Sun.COM 		case STMF_LU_PROP_SERIAL_NUM:
2277*9585STim.Szeto@Sun.COM 			if (diskLu->serialNumValid == B_FALSE) {
2278*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
2279*9585STim.Szeto@Sun.COM 			}
2280*9585STim.Szeto@Sun.COM 			if ((reqLen = strlcpy(propVal, diskLu->serialNum,
2281*9585STim.Szeto@Sun.COM 			    *propLen)) >= *propLen) {
2282*9585STim.Szeto@Sun.COM 				*propLen = reqLen + 1;
2283*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
2284*9585STim.Szeto@Sun.COM 			}
2285*9585STim.Szeto@Sun.COM 			break;
2286*9585STim.Szeto@Sun.COM 		case STMF_LU_PROP_SIZE:
2287*9585STim.Szeto@Sun.COM 			if (diskLu->luSizeValid == B_FALSE) {
2288*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
2289*9585STim.Szeto@Sun.COM 			}
2290*9585STim.Szeto@Sun.COM 			(void) snprintf(propVal, *propLen, "%llu",
2291*9585STim.Szeto@Sun.COM 			    (u_longlong_t)diskLu->luSize);
2292*9585STim.Szeto@Sun.COM 			break;
2293*9585STim.Szeto@Sun.COM 		case STMF_LU_PROP_ALIAS:
2294*9585STim.Szeto@Sun.COM 			if (diskLu->luAliasValid == B_FALSE) {
2295*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
2296*9585STim.Szeto@Sun.COM 			}
2297*9585STim.Szeto@Sun.COM 			if ((reqLen = strlcpy(propVal, diskLu->luAlias,
2298*9585STim.Szeto@Sun.COM 			    *propLen)) >= *propLen) {
2299*9585STim.Szeto@Sun.COM 				*propLen = reqLen + 1;
2300*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
2301*9585STim.Szeto@Sun.COM 			}
2302*9585STim.Szeto@Sun.COM 			break;
2303*9585STim.Szeto@Sun.COM 		case STMF_LU_PROP_VID:
2304*9585STim.Szeto@Sun.COM 			if (diskLu->vidValid == B_FALSE) {
2305*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
2306*9585STim.Szeto@Sun.COM 			}
2307*9585STim.Szeto@Sun.COM 			if (*propLen <= sizeof (diskLu->vid)) {
2308*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
2309*9585STim.Szeto@Sun.COM 			}
2310*9585STim.Szeto@Sun.COM 			bcopy(diskLu->vid, propVal, sizeof (diskLu->vid));
2311*9585STim.Szeto@Sun.COM 			propVal[sizeof (diskLu->vid)] = 0;
2312*9585STim.Szeto@Sun.COM 			break;
2313*9585STim.Szeto@Sun.COM 		case STMF_LU_PROP_PID:
2314*9585STim.Szeto@Sun.COM 			if (diskLu->pidValid == B_FALSE) {
2315*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
2316*9585STim.Szeto@Sun.COM 			}
2317*9585STim.Szeto@Sun.COM 			if (*propLen <= sizeof (diskLu->pid)) {
2318*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
2319*9585STim.Szeto@Sun.COM 			}
2320*9585STim.Szeto@Sun.COM 			bcopy(diskLu->pid, propVal, sizeof (diskLu->pid));
2321*9585STim.Szeto@Sun.COM 			propVal[sizeof (diskLu->pid)] = 0;
2322*9585STim.Szeto@Sun.COM 			break;
2323*9585STim.Szeto@Sun.COM 		case STMF_LU_PROP_WRITE_PROTECT:
2324*9585STim.Szeto@Sun.COM 			if (diskLu->writeProtectEnableValid == B_FALSE) {
2325*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
2326*9585STim.Szeto@Sun.COM 			}
2327*9585STim.Szeto@Sun.COM 			if (diskLu->writeProtectEnable) {
2328*9585STim.Szeto@Sun.COM 				if ((reqLen = strlcpy(propVal, "true",
2329*9585STim.Szeto@Sun.COM 				    *propLen)) >= *propLen) {
2330*9585STim.Szeto@Sun.COM 					*propLen = reqLen + 1;
2331*9585STim.Szeto@Sun.COM 					return (STMF_ERROR_INVALID_ARG);
2332*9585STim.Szeto@Sun.COM 				}
2333*9585STim.Szeto@Sun.COM 			} else {
2334*9585STim.Szeto@Sun.COM 				if ((reqLen = strlcpy(propVal, "false",
2335*9585STim.Szeto@Sun.COM 				    *propLen)) >= *propLen) {
2336*9585STim.Szeto@Sun.COM 					*propLen = reqLen + 1;
2337*9585STim.Szeto@Sun.COM 					return (STMF_ERROR_INVALID_ARG);
2338*9585STim.Szeto@Sun.COM 				}
2339*9585STim.Szeto@Sun.COM 			}
2340*9585STim.Szeto@Sun.COM 			break;
2341*9585STim.Szeto@Sun.COM 		case STMF_LU_PROP_WRITE_CACHE_DISABLE:
2342*9585STim.Szeto@Sun.COM 			if (diskLu->writebackCacheDisableValid == B_FALSE) {
2343*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_NO_PROP);
2344*9585STim.Szeto@Sun.COM 			}
2345*9585STim.Szeto@Sun.COM 			if (diskLu->writebackCacheDisable) {
2346*9585STim.Szeto@Sun.COM 				if ((reqLen = strlcpy(propVal, "true",
2347*9585STim.Szeto@Sun.COM 				    *propLen)) >= *propLen) {
2348*9585STim.Szeto@Sun.COM 					*propLen = reqLen + 1;
2349*9585STim.Szeto@Sun.COM 					return (STMF_ERROR_INVALID_ARG);
2350*9585STim.Szeto@Sun.COM 				}
2351*9585STim.Szeto@Sun.COM 			} else {
2352*9585STim.Szeto@Sun.COM 				if ((reqLen = strlcpy(propVal, "false",
2353*9585STim.Szeto@Sun.COM 				    *propLen)) >= *propLen) {
2354*9585STim.Szeto@Sun.COM 					*propLen = reqLen + 1;
2355*9585STim.Szeto@Sun.COM 					return (STMF_ERROR_INVALID_ARG);
2356*9585STim.Szeto@Sun.COM 				}
2357*9585STim.Szeto@Sun.COM 			}
2358*9585STim.Szeto@Sun.COM 			break;
2359*9585STim.Szeto@Sun.COM 		default:
2360*9585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NO_PROP;
2361*9585STim.Szeto@Sun.COM 			break;
2362*9585STim.Szeto@Sun.COM 	}
2363*9585STim.Szeto@Sun.COM 
2364*9585STim.Szeto@Sun.COM 	return (ret);
2365*9585STim.Szeto@Sun.COM }
2366*9585STim.Szeto@Sun.COM 
2367*9585STim.Szeto@Sun.COM /*
2368*9585STim.Szeto@Sun.COM  * setDiskProp
2369*9585STim.Szeto@Sun.COM  *
2370*9585STim.Szeto@Sun.COM  * Purpose: set properties for resource of type disk
2371*9585STim.Szeto@Sun.COM  *
2372*9585STim.Szeto@Sun.COM  * hdl - allocated luResourceImpl
2373*9585STim.Szeto@Sun.COM  * resourceProp - valid resource identifier
2374*9585STim.Szeto@Sun.COM  * propVal - valid resource value
2375*9585STim.Szeto@Sun.COM  */
2376*9585STim.Szeto@Sun.COM static int
2377*9585STim.Szeto@Sun.COM setDiskProp(luResourceImpl *hdl, uint32_t resourceProp, const char *propVal)
2378*9585STim.Szeto@Sun.COM {
2379*9585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
2380*9585STim.Szeto@Sun.COM 	int i;
2381*9585STim.Szeto@Sun.COM 	diskResource *diskLu = hdl->resource;
2382*9585STim.Szeto@Sun.COM 	unsigned long long numericProp = 0;
2383*9585STim.Szeto@Sun.COM 	char guidProp[LU_ASCII_GUID_SIZE + 1];
2384*9585STim.Szeto@Sun.COM 	char ouiProp[OUI_ASCII_SIZE + 1];
2385*9585STim.Szeto@Sun.COM 	unsigned int oui[OUI_SIZE];
2386*9585STim.Szeto@Sun.COM 	unsigned int guid[LU_GUID_SIZE];
2387*9585STim.Szeto@Sun.COM 	int propSize;
2388*9585STim.Szeto@Sun.COM 
2389*9585STim.Szeto@Sun.COM 
2390*9585STim.Szeto@Sun.COM 	if (propVal == NULL) {
2391*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
2392*9585STim.Szeto@Sun.COM 	}
2393*9585STim.Szeto@Sun.COM 
2394*9585STim.Szeto@Sun.COM 	switch (resourceProp) {
2395*9585STim.Szeto@Sun.COM 		case STMF_LU_PROP_ALIAS:
2396*9585STim.Szeto@Sun.COM 			if (strlcpy(diskLu->luAlias, propVal,
2397*9585STim.Szeto@Sun.COM 			    sizeof (diskLu->luAlias)) >=
2398*9585STim.Szeto@Sun.COM 			    sizeof (diskLu->luAlias)) {
2399*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
2400*9585STim.Szeto@Sun.COM 			}
2401*9585STim.Szeto@Sun.COM 			diskLu->luAliasValid = B_TRUE;
2402*9585STim.Szeto@Sun.COM 			break;
2403*9585STim.Szeto@Sun.COM 		case STMF_LU_PROP_BLOCK_SIZE:
2404*9585STim.Szeto@Sun.COM 			(void) sscanf(propVal, "%llu", &numericProp);
2405*9585STim.Szeto@Sun.COM 			if (numericProp > UINT16_MAX) {
2406*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
2407*9585STim.Szeto@Sun.COM 			}
2408*9585STim.Szeto@Sun.COM 			diskLu->blkSize = numericProp;
2409*9585STim.Szeto@Sun.COM 			diskLu->blkSizeValid = B_TRUE;
2410*9585STim.Szeto@Sun.COM 			break;
2411*9585STim.Szeto@Sun.COM 		case STMF_LU_PROP_COMPANY_ID:
2412*9585STim.Szeto@Sun.COM 			if ((strlcpy(ouiProp, propVal, sizeof (ouiProp))) >=
2413*9585STim.Szeto@Sun.COM 			    sizeof (ouiProp)) {
2414*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
2415*9585STim.Szeto@Sun.COM 			}
2416*9585STim.Szeto@Sun.COM 			if (checkHexUpper(ouiProp) != 0) {
2417*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
2418*9585STim.Szeto@Sun.COM 			}
2419*9585STim.Szeto@Sun.COM 			(void) sscanf(ouiProp, "%2X%2X%2X",
2420*9585STim.Szeto@Sun.COM 			    &oui[0], &oui[1], &oui[2]);
2421*9585STim.Szeto@Sun.COM 
2422*9585STim.Szeto@Sun.COM 			diskLu->companyId = 0;
2423*9585STim.Szeto@Sun.COM 			diskLu->companyId += oui[0] << 16;
2424*9585STim.Szeto@Sun.COM 			diskLu->companyId += oui[1] << 8;
2425*9585STim.Szeto@Sun.COM 			diskLu->companyId += oui[2];
2426*9585STim.Szeto@Sun.COM 			diskLu->companyIdValid = B_TRUE;
2427*9585STim.Szeto@Sun.COM 			break;
2428*9585STim.Szeto@Sun.COM 		case STMF_LU_PROP_GUID:
2429*9585STim.Szeto@Sun.COM 			if (strlen(propVal) != LU_ASCII_GUID_SIZE) {
2430*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
2431*9585STim.Szeto@Sun.COM 			}
2432*9585STim.Szeto@Sun.COM 
2433*9585STim.Szeto@Sun.COM 			if ((strlcpy(guidProp, propVal, sizeof (guidProp))) >=
2434*9585STim.Szeto@Sun.COM 			    sizeof (guidProp)) {
2435*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
2436*9585STim.Szeto@Sun.COM 			}
2437*9585STim.Szeto@Sun.COM 
2438*9585STim.Szeto@Sun.COM 			if (checkHexUpper(guidProp) != 0) {
2439*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
2440*9585STim.Szeto@Sun.COM 			}
2441*9585STim.Szeto@Sun.COM 
2442*9585STim.Szeto@Sun.COM 			(void) sscanf(guidProp,
2443*9585STim.Szeto@Sun.COM 			    "%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X",
2444*9585STim.Szeto@Sun.COM 			    &guid[0], &guid[1], &guid[2], &guid[3], &guid[4],
2445*9585STim.Szeto@Sun.COM 			    &guid[5], &guid[6], &guid[7], &guid[8], &guid[9],
2446*9585STim.Szeto@Sun.COM 			    &guid[10], &guid[11], &guid[12], &guid[13],
2447*9585STim.Szeto@Sun.COM 			    &guid[14], &guid[15]);
2448*9585STim.Szeto@Sun.COM 			for (i = 0; i < sizeof (diskLu->luGuid); i++) {
2449*9585STim.Szeto@Sun.COM 				diskLu->luGuid[i] = guid[i];
2450*9585STim.Szeto@Sun.COM 			}
2451*9585STim.Szeto@Sun.COM 			diskLu->luGuidValid = B_TRUE;
2452*9585STim.Szeto@Sun.COM 			break;
2453*9585STim.Szeto@Sun.COM 		case STMF_LU_PROP_FILENAME:
2454*9585STim.Szeto@Sun.COM 			if ((strlcpy(diskLu->luDataFileName, propVal,
2455*9585STim.Szeto@Sun.COM 			    sizeof (diskLu->luDataFileName))) >=
2456*9585STim.Szeto@Sun.COM 			    sizeof (diskLu->luDataFileName)) {
2457*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
2458*9585STim.Szeto@Sun.COM 			}
2459*9585STim.Szeto@Sun.COM 			diskLu->luDataFileNameValid = B_TRUE;
2460*9585STim.Szeto@Sun.COM 			break;
2461*9585STim.Szeto@Sun.COM 		case STMF_LU_PROP_META_FILENAME:
2462*9585STim.Szeto@Sun.COM 			if ((strlcpy(diskLu->luMetaFileName, propVal,
2463*9585STim.Szeto@Sun.COM 			    sizeof (diskLu->luMetaFileName))) >=
2464*9585STim.Szeto@Sun.COM 			    sizeof (diskLu->luMetaFileName)) {
2465*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
2466*9585STim.Szeto@Sun.COM 			}
2467*9585STim.Szeto@Sun.COM 			diskLu->luMetaFileNameValid = B_TRUE;
2468*9585STim.Szeto@Sun.COM 			break;
2469*9585STim.Szeto@Sun.COM 		case STMF_LU_PROP_PID:
2470*9585STim.Szeto@Sun.COM 			if ((propSize = strlen(propVal)) >
2471*9585STim.Szeto@Sun.COM 			    sizeof (diskLu->pid)) {
2472*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
2473*9585STim.Szeto@Sun.COM 			}
2474*9585STim.Szeto@Sun.COM 			(void) strncpy(diskLu->pid, propVal, propSize);
2475*9585STim.Szeto@Sun.COM 			diskLu->pidValid = B_TRUE;
2476*9585STim.Szeto@Sun.COM 			break;
2477*9585STim.Szeto@Sun.COM 		case STMF_LU_PROP_SERIAL_NUM:
2478*9585STim.Szeto@Sun.COM 			if ((propSize = strlen(propVal)) >
2479*9585STim.Szeto@Sun.COM 			    (sizeof (diskLu->serialNum) - 1)) {
2480*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
2481*9585STim.Szeto@Sun.COM 			}
2482*9585STim.Szeto@Sun.COM 			(void) strncpy(diskLu->serialNum, propVal, propSize);
2483*9585STim.Szeto@Sun.COM 			diskLu->serialNumValid = B_TRUE;
2484*9585STim.Szeto@Sun.COM 			break;
2485*9585STim.Szeto@Sun.COM 		case STMF_LU_PROP_SIZE:
2486*9585STim.Szeto@Sun.COM 			if ((niceStrToNum(propVal, &diskLu->luSize) != 0)) {
2487*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
2488*9585STim.Szeto@Sun.COM 			}
2489*9585STim.Szeto@Sun.COM 			diskLu->luSizeValid = B_TRUE;
2490*9585STim.Szeto@Sun.COM 			break;
2491*9585STim.Szeto@Sun.COM 		case STMF_LU_PROP_VID:
2492*9585STim.Szeto@Sun.COM 			if ((propSize = strlen(propVal)) >
2493*9585STim.Szeto@Sun.COM 			    sizeof (diskLu->vid)) {
2494*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_PROPSIZE);
2495*9585STim.Szeto@Sun.COM 			}
2496*9585STim.Szeto@Sun.COM 			(void) strncpy(diskLu->vid, propVal, propSize);
2497*9585STim.Szeto@Sun.COM 			diskLu->vidValid = B_TRUE;
2498*9585STim.Szeto@Sun.COM 			break;
2499*9585STim.Szeto@Sun.COM 		case STMF_LU_PROP_WRITE_PROTECT:
2500*9585STim.Szeto@Sun.COM 			if (strcasecmp(propVal, "TRUE") == 0) {
2501*9585STim.Szeto@Sun.COM 				diskLu->writeProtectEnable = B_TRUE;
2502*9585STim.Szeto@Sun.COM 			} else if (strcasecmp(propVal, "FALSE") == 0) {
2503*9585STim.Szeto@Sun.COM 				diskLu->writeProtectEnable = B_FALSE;
2504*9585STim.Szeto@Sun.COM 			} else {
2505*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
2506*9585STim.Szeto@Sun.COM 			}
2507*9585STim.Szeto@Sun.COM 			diskLu->writeProtectEnableValid = B_TRUE;
2508*9585STim.Szeto@Sun.COM 			break;
2509*9585STim.Szeto@Sun.COM 		case STMF_LU_PROP_WRITE_CACHE_DISABLE:
2510*9585STim.Szeto@Sun.COM 			if (strcasecmp(propVal, "TRUE") == 0) {
2511*9585STim.Szeto@Sun.COM 				diskLu->writebackCacheDisable = B_TRUE;
2512*9585STim.Szeto@Sun.COM 			} else if (strcasecmp(propVal, "FALSE") == 0) {
2513*9585STim.Szeto@Sun.COM 				diskLu->writebackCacheDisable = B_FALSE;
2514*9585STim.Szeto@Sun.COM 			} else {
2515*9585STim.Szeto@Sun.COM 				return (STMF_ERROR_INVALID_ARG);
2516*9585STim.Szeto@Sun.COM 			}
2517*9585STim.Szeto@Sun.COM 			diskLu->writebackCacheDisableValid = B_TRUE;
2518*9585STim.Szeto@Sun.COM 			break;
2519*9585STim.Szeto@Sun.COM 		default:
2520*9585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NO_PROP;
2521*9585STim.Szeto@Sun.COM 			break;
2522*9585STim.Szeto@Sun.COM 	}
2523*9585STim.Szeto@Sun.COM 	return (ret);
2524*9585STim.Szeto@Sun.COM }
2525*9585STim.Szeto@Sun.COM 
2526*9585STim.Szeto@Sun.COM static int
2527*9585STim.Szeto@Sun.COM checkHexUpper(char *buf)
2528*9585STim.Szeto@Sun.COM {
2529*9585STim.Szeto@Sun.COM 	int i;
2530*9585STim.Szeto@Sun.COM 
2531*9585STim.Szeto@Sun.COM 	for (i = 0; i < strlen(buf); i++) {
2532*9585STim.Szeto@Sun.COM 		if (isxdigit(buf[i])) {
2533*9585STim.Szeto@Sun.COM 			buf[i] = toupper(buf[i]);
2534*9585STim.Szeto@Sun.COM 			continue;
2535*9585STim.Szeto@Sun.COM 		}
2536*9585STim.Szeto@Sun.COM 		return (-1);
2537*9585STim.Szeto@Sun.COM 	}
2538*9585STim.Szeto@Sun.COM 
2539*9585STim.Szeto@Sun.COM 	return (0);
2540*9585STim.Szeto@Sun.COM }
2541*9585STim.Szeto@Sun.COM 
2542*9585STim.Szeto@Sun.COM /*
2543*9585STim.Szeto@Sun.COM  * Given a numeric suffix, convert the value into a number of bits that the
2544*9585STim.Szeto@Sun.COM  * resulting value must be shifted.
2545*9585STim.Szeto@Sun.COM  * Code lifted from libzfs_util.c
2546*9585STim.Szeto@Sun.COM  */
2547*9585STim.Szeto@Sun.COM static int
2548*9585STim.Szeto@Sun.COM strToShift(const char *buf)
2549*9585STim.Szeto@Sun.COM {
2550*9585STim.Szeto@Sun.COM 	const char *ends = "BKMGTPE";
2551*9585STim.Szeto@Sun.COM 	int i;
2552*9585STim.Szeto@Sun.COM 
2553*9585STim.Szeto@Sun.COM 	if (buf[0] == '\0')
2554*9585STim.Szeto@Sun.COM 		return (0);
2555*9585STim.Szeto@Sun.COM 
2556*9585STim.Szeto@Sun.COM 	for (i = 0; i < strlen(ends); i++) {
2557*9585STim.Szeto@Sun.COM 		if (toupper(buf[0]) == ends[i])
2558*9585STim.Szeto@Sun.COM 			return (10*i);
2559*9585STim.Szeto@Sun.COM 	}
2560*9585STim.Szeto@Sun.COM 
2561*9585STim.Szeto@Sun.COM 	return (-1);
2562*9585STim.Szeto@Sun.COM }
2563*9585STim.Szeto@Sun.COM 
2564*9585STim.Szeto@Sun.COM int
2565*9585STim.Szeto@Sun.COM stmfFreeLuResource(luResource hdl)
2566*9585STim.Szeto@Sun.COM {
2567*9585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
2568*9585STim.Szeto@Sun.COM 	if (hdl == NULL) {
2569*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
2570*9585STim.Szeto@Sun.COM 	}
2571*9585STim.Szeto@Sun.COM 
2572*9585STim.Szeto@Sun.COM 	luResourceImpl *hdlImpl = hdl;
2573*9585STim.Szeto@Sun.COM 	free(hdlImpl->resource);
2574*9585STim.Szeto@Sun.COM 	free(hdlImpl);
2575*9585STim.Szeto@Sun.COM 	return (ret);
2576*9585STim.Szeto@Sun.COM }
2577*9585STim.Szeto@Sun.COM 
2578*9585STim.Szeto@Sun.COM /*
2579*9585STim.Szeto@Sun.COM  * Convert a string of the form '100G' into a real number. Used when setting
2580*9585STim.Szeto@Sun.COM  * the size of a logical unit.
2581*9585STim.Szeto@Sun.COM  * Code lifted from libzfs_util.c
2582*9585STim.Szeto@Sun.COM  */
2583*9585STim.Szeto@Sun.COM static int
2584*9585STim.Szeto@Sun.COM niceStrToNum(const char *value, uint64_t *num)
2585*9585STim.Szeto@Sun.COM {
2586*9585STim.Szeto@Sun.COM 	char *end;
2587*9585STim.Szeto@Sun.COM 	int shift;
2588*9585STim.Szeto@Sun.COM 
2589*9585STim.Szeto@Sun.COM 	*num = 0;
2590*9585STim.Szeto@Sun.COM 
2591*9585STim.Szeto@Sun.COM 	/* Check to see if this looks like a number.  */
2592*9585STim.Szeto@Sun.COM 	if ((value[0] < '0' || value[0] > '9') && value[0] != '.') {
2593*9585STim.Szeto@Sun.COM 		return (-1);
2594*9585STim.Szeto@Sun.COM 	}
2595*9585STim.Szeto@Sun.COM 
2596*9585STim.Szeto@Sun.COM 	/* Rely on stroull() to process the numeric portion.  */
2597*9585STim.Szeto@Sun.COM 	errno = 0;
2598*9585STim.Szeto@Sun.COM 	*num = strtoull(value, &end, 10);
2599*9585STim.Szeto@Sun.COM 
2600*9585STim.Szeto@Sun.COM 	/*
2601*9585STim.Szeto@Sun.COM 	 * Check for ERANGE, which indicates that the value is too large to fit
2602*9585STim.Szeto@Sun.COM 	 * in a 64-bit value.
2603*9585STim.Szeto@Sun.COM 	 */
2604*9585STim.Szeto@Sun.COM 	if (errno == ERANGE) {
2605*9585STim.Szeto@Sun.COM 		return (-1);
2606*9585STim.Szeto@Sun.COM 	}
2607*9585STim.Szeto@Sun.COM 
2608*9585STim.Szeto@Sun.COM 	/*
2609*9585STim.Szeto@Sun.COM 	 * If we have a decimal value, then do the computation with floating
2610*9585STim.Szeto@Sun.COM 	 * point arithmetic.  Otherwise, use standard arithmetic.
2611*9585STim.Szeto@Sun.COM 	 */
2612*9585STim.Szeto@Sun.COM 	if (*end == '.') {
2613*9585STim.Szeto@Sun.COM 		double fval = strtod(value, &end);
2614*9585STim.Szeto@Sun.COM 
2615*9585STim.Szeto@Sun.COM 		if ((shift = strToShift(end)) == -1) {
2616*9585STim.Szeto@Sun.COM 			return (-1);
2617*9585STim.Szeto@Sun.COM 		}
2618*9585STim.Szeto@Sun.COM 
2619*9585STim.Szeto@Sun.COM 		fval *= pow(2, shift);
2620*9585STim.Szeto@Sun.COM 
2621*9585STim.Szeto@Sun.COM 		if (fval > UINT64_MAX) {
2622*9585STim.Szeto@Sun.COM 			return (-1);
2623*9585STim.Szeto@Sun.COM 		}
2624*9585STim.Szeto@Sun.COM 
2625*9585STim.Szeto@Sun.COM 		*num = (uint64_t)fval;
2626*9585STim.Szeto@Sun.COM 	} else {
2627*9585STim.Szeto@Sun.COM 		if ((shift = strToShift(end)) == -1) {
2628*9585STim.Szeto@Sun.COM 			return (-1);
2629*9585STim.Szeto@Sun.COM 		}
2630*9585STim.Szeto@Sun.COM 
2631*9585STim.Szeto@Sun.COM 		/* Check for overflow */
2632*9585STim.Szeto@Sun.COM 		if (shift >= 64 || (*num << shift) >> shift != *num) {
2633*9585STim.Szeto@Sun.COM 			return (-1);
2634*9585STim.Szeto@Sun.COM 		}
2635*9585STim.Szeto@Sun.COM 
2636*9585STim.Szeto@Sun.COM 		*num <<= shift;
2637*9585STim.Szeto@Sun.COM 	}
2638*9585STim.Szeto@Sun.COM 
2639*9585STim.Szeto@Sun.COM 	return (0);
2640*9585STim.Szeto@Sun.COM }
2641*9585STim.Szeto@Sun.COM 
2642*9585STim.Szeto@Sun.COM /*
26437836SJohn.Forte@Sun.COM  * stmfCreateTargetGroup
26447836SJohn.Forte@Sun.COM  *
26457836SJohn.Forte@Sun.COM  * Purpose: Create a local port group
26467836SJohn.Forte@Sun.COM  *
26477836SJohn.Forte@Sun.COM  * targetGroupName - name of local port group to create
26487836SJohn.Forte@Sun.COM  */
26497836SJohn.Forte@Sun.COM int
26507836SJohn.Forte@Sun.COM stmfCreateTargetGroup(stmfGroupName *targetGroupName)
26517836SJohn.Forte@Sun.COM {
26527836SJohn.Forte@Sun.COM 	int ret;
26537836SJohn.Forte@Sun.COM 	int fd;
26547836SJohn.Forte@Sun.COM 
26557836SJohn.Forte@Sun.COM 	if (targetGroupName == NULL ||
26567836SJohn.Forte@Sun.COM 	    (strnlen((char *)targetGroupName, sizeof (stmfGroupName))
26577836SJohn.Forte@Sun.COM 	    == sizeof (stmfGroupName))) {
26587836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
26597836SJohn.Forte@Sun.COM 	}
26607836SJohn.Forte@Sun.COM 
26617836SJohn.Forte@Sun.COM 	/* Check to ensure service exists */
26627836SJohn.Forte@Sun.COM 	if (psCheckService() != STMF_STATUS_SUCCESS) {
26637836SJohn.Forte@Sun.COM 		return (STMF_ERROR_SERVICE_NOT_FOUND);
26647836SJohn.Forte@Sun.COM 	}
26657836SJohn.Forte@Sun.COM 
26667836SJohn.Forte@Sun.COM 	/* call init */
26677836SJohn.Forte@Sun.COM 	ret = initializeConfig();
26687836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
26697836SJohn.Forte@Sun.COM 		return (ret);
26707836SJohn.Forte@Sun.COM 	}
26717836SJohn.Forte@Sun.COM 
26727836SJohn.Forte@Sun.COM 	/*
26737836SJohn.Forte@Sun.COM 	 * Open control node for stmf
26747836SJohn.Forte@Sun.COM 	 */
26757836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
26767836SJohn.Forte@Sun.COM 		return (ret);
26777836SJohn.Forte@Sun.COM 
26787836SJohn.Forte@Sun.COM 	/*
26797836SJohn.Forte@Sun.COM 	 * Add the group to the driver
26807836SJohn.Forte@Sun.COM 	 */
26817836SJohn.Forte@Sun.COM 	if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_TARGET_GROUP,
26827836SJohn.Forte@Sun.COM 	    targetGroupName)) != STMF_STATUS_SUCCESS) {
26837836SJohn.Forte@Sun.COM 		goto done;
26847836SJohn.Forte@Sun.COM 	}
26857836SJohn.Forte@Sun.COM 
2686*9585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
2687*9585STim.Szeto@Sun.COM 		goto done;
2688*9585STim.Szeto@Sun.COM 	}
2689*9585STim.Szeto@Sun.COM 
26907836SJohn.Forte@Sun.COM 	/*
26917836SJohn.Forte@Sun.COM 	 * If the add to the driver was successful, add it to the persistent
26927836SJohn.Forte@Sun.COM 	 * store.
26937836SJohn.Forte@Sun.COM 	 */
26947836SJohn.Forte@Sun.COM 	ret = psCreateTargetGroup((char *)targetGroupName);
26957836SJohn.Forte@Sun.COM 	switch (ret) {
26967836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
26977836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
26987836SJohn.Forte@Sun.COM 			break;
26997836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_EXISTS:
27007836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_EXISTS;
27017836SJohn.Forte@Sun.COM 			break;
27027836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
27037836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
27047836SJohn.Forte@Sun.COM 			break;
27057836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
27067836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
27077836SJohn.Forte@Sun.COM 			break;
27087836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
27097836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
27107836SJohn.Forte@Sun.COM 			break;
27117836SJohn.Forte@Sun.COM 		default:
27127836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
27137836SJohn.Forte@Sun.COM 			    "stmfCreateTargetGroup:psCreateTargetGroup"
27147836SJohn.Forte@Sun.COM 			    ":error(%d)", ret);
27157836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
27167836SJohn.Forte@Sun.COM 			break;
27177836SJohn.Forte@Sun.COM 	}
27187836SJohn.Forte@Sun.COM 
27197836SJohn.Forte@Sun.COM done:
27207836SJohn.Forte@Sun.COM 	(void) close(fd);
27217836SJohn.Forte@Sun.COM 	return (ret);
27227836SJohn.Forte@Sun.COM }
27237836SJohn.Forte@Sun.COM 
27247836SJohn.Forte@Sun.COM /*
27257836SJohn.Forte@Sun.COM  * stmfDeleteHostGroup
27267836SJohn.Forte@Sun.COM  *
27277836SJohn.Forte@Sun.COM  * Purpose: Delete an initiator or local port group
27287836SJohn.Forte@Sun.COM  *
27297836SJohn.Forte@Sun.COM  * hostGroupName - group to delete
27307836SJohn.Forte@Sun.COM  */
27317836SJohn.Forte@Sun.COM int
27327836SJohn.Forte@Sun.COM stmfDeleteHostGroup(stmfGroupName *hostGroupName)
27337836SJohn.Forte@Sun.COM {
27347836SJohn.Forte@Sun.COM 	int ret;
27357836SJohn.Forte@Sun.COM 	int fd;
27367836SJohn.Forte@Sun.COM 
27377836SJohn.Forte@Sun.COM 	if (hostGroupName == NULL) {
27387836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
27397836SJohn.Forte@Sun.COM 	}
27407836SJohn.Forte@Sun.COM 
27417836SJohn.Forte@Sun.COM 	/* Check to ensure service exists */
27427836SJohn.Forte@Sun.COM 	if (psCheckService() != STMF_STATUS_SUCCESS) {
27437836SJohn.Forte@Sun.COM 		return (STMF_ERROR_SERVICE_NOT_FOUND);
27447836SJohn.Forte@Sun.COM 	}
27457836SJohn.Forte@Sun.COM 
27467836SJohn.Forte@Sun.COM 	/* call init */
27477836SJohn.Forte@Sun.COM 	ret = initializeConfig();
27487836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
27497836SJohn.Forte@Sun.COM 		return (ret);
27507836SJohn.Forte@Sun.COM 	}
27517836SJohn.Forte@Sun.COM 
27527836SJohn.Forte@Sun.COM 	/*
27537836SJohn.Forte@Sun.COM 	 * Open control node for stmf
27547836SJohn.Forte@Sun.COM 	 */
27557836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
27567836SJohn.Forte@Sun.COM 		return (ret);
27577836SJohn.Forte@Sun.COM 
27587836SJohn.Forte@Sun.COM 	/*
27597836SJohn.Forte@Sun.COM 	 * Remove the group from the driver
27607836SJohn.Forte@Sun.COM 	 */
27617836SJohn.Forte@Sun.COM 	if ((ret = groupIoctl(fd, STMF_IOCTL_REMOVE_HOST_GROUP,
27627836SJohn.Forte@Sun.COM 	    hostGroupName)) != STMF_STATUS_SUCCESS) {
27637836SJohn.Forte@Sun.COM 		goto done;
27647836SJohn.Forte@Sun.COM 	}
27657836SJohn.Forte@Sun.COM 
2766*9585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
2767*9585STim.Szeto@Sun.COM 		goto done;
2768*9585STim.Szeto@Sun.COM 	}
2769*9585STim.Szeto@Sun.COM 
27707836SJohn.Forte@Sun.COM 	/*
27717836SJohn.Forte@Sun.COM 	 * If the remove from the driver was successful, remove it from the
27727836SJohn.Forte@Sun.COM 	 * persistent store.
27737836SJohn.Forte@Sun.COM 	 */
27747836SJohn.Forte@Sun.COM 	ret = psDeleteHostGroup((char *)hostGroupName);
27757836SJohn.Forte@Sun.COM 	switch (ret) {
27767836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
27777836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
27787836SJohn.Forte@Sun.COM 			break;
27797836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
27807836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
27817836SJohn.Forte@Sun.COM 			break;
27827836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
27837836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
27847836SJohn.Forte@Sun.COM 			break;
27857836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
27867836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
27877836SJohn.Forte@Sun.COM 			break;
27887836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
27897836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
27907836SJohn.Forte@Sun.COM 			break;
27917836SJohn.Forte@Sun.COM 		default:
27927836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
27937836SJohn.Forte@Sun.COM 			    "stmfDeleteHostGroup:psDeleteHostGroup:error(%d)",
27947836SJohn.Forte@Sun.COM 			    ret);
27957836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
27967836SJohn.Forte@Sun.COM 			break;
27977836SJohn.Forte@Sun.COM 	}
27987836SJohn.Forte@Sun.COM 
27997836SJohn.Forte@Sun.COM done:
28007836SJohn.Forte@Sun.COM 	(void) close(fd);
28017836SJohn.Forte@Sun.COM 	return (ret);
28027836SJohn.Forte@Sun.COM }
28037836SJohn.Forte@Sun.COM 
28047836SJohn.Forte@Sun.COM /*
28057836SJohn.Forte@Sun.COM  * stmfDeleteTargetGroup
28067836SJohn.Forte@Sun.COM  *
28077836SJohn.Forte@Sun.COM  * Purpose: Delete an initiator or local port group
28087836SJohn.Forte@Sun.COM  *
28097836SJohn.Forte@Sun.COM  * targetGroupName - group to delete
28107836SJohn.Forte@Sun.COM  */
28117836SJohn.Forte@Sun.COM int
28127836SJohn.Forte@Sun.COM stmfDeleteTargetGroup(stmfGroupName *targetGroupName)
28137836SJohn.Forte@Sun.COM {
28147836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
28157836SJohn.Forte@Sun.COM 	int fd;
28167836SJohn.Forte@Sun.COM 
28177836SJohn.Forte@Sun.COM 	if (targetGroupName == NULL) {
28187836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
28197836SJohn.Forte@Sun.COM 	}
28207836SJohn.Forte@Sun.COM 
28217836SJohn.Forte@Sun.COM 	/* Check to ensure service exists */
28227836SJohn.Forte@Sun.COM 	if (psCheckService() != STMF_STATUS_SUCCESS) {
28237836SJohn.Forte@Sun.COM 		return (STMF_ERROR_SERVICE_NOT_FOUND);
28247836SJohn.Forte@Sun.COM 	}
28257836SJohn.Forte@Sun.COM 
28267836SJohn.Forte@Sun.COM 	/* call init */
28277836SJohn.Forte@Sun.COM 	ret = initializeConfig();
28287836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
28297836SJohn.Forte@Sun.COM 		return (ret);
28307836SJohn.Forte@Sun.COM 	}
28317836SJohn.Forte@Sun.COM 
28327836SJohn.Forte@Sun.COM 	/*
28337836SJohn.Forte@Sun.COM 	 * Open control node for stmf
28347836SJohn.Forte@Sun.COM 	 */
28357836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
28367836SJohn.Forte@Sun.COM 		return (ret);
28377836SJohn.Forte@Sun.COM 
28387836SJohn.Forte@Sun.COM 	/*
28397836SJohn.Forte@Sun.COM 	 * Remove the group from the driver
28407836SJohn.Forte@Sun.COM 	 */
28417836SJohn.Forte@Sun.COM 	if ((ret = groupIoctl(fd, STMF_IOCTL_REMOVE_TARGET_GROUP,
28427836SJohn.Forte@Sun.COM 	    targetGroupName)) != STMF_STATUS_SUCCESS) {
28437836SJohn.Forte@Sun.COM 		goto done;
28447836SJohn.Forte@Sun.COM 	}
28457836SJohn.Forte@Sun.COM 
2846*9585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
2847*9585STim.Szeto@Sun.COM 		goto done;
2848*9585STim.Szeto@Sun.COM 	}
2849*9585STim.Szeto@Sun.COM 
28507836SJohn.Forte@Sun.COM 	/*
28517836SJohn.Forte@Sun.COM 	 * If the remove from the driver was successful, remove it from the
28527836SJohn.Forte@Sun.COM 	 * persistent store.
28537836SJohn.Forte@Sun.COM 	 */
28547836SJohn.Forte@Sun.COM 	ret = psDeleteTargetGroup((char *)targetGroupName);
28557836SJohn.Forte@Sun.COM 	switch (ret) {
28567836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
28577836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
28587836SJohn.Forte@Sun.COM 			break;
28597836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
28607836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
28617836SJohn.Forte@Sun.COM 			break;
28627836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
28637836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
28647836SJohn.Forte@Sun.COM 			break;
28657836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
28667836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
28677836SJohn.Forte@Sun.COM 			break;
28687836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
28697836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
28707836SJohn.Forte@Sun.COM 			break;
28717836SJohn.Forte@Sun.COM 		default:
28727836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
28737836SJohn.Forte@Sun.COM 			    "stmfDeleteTargetGroup:psDeleteTargetGroup"
28747836SJohn.Forte@Sun.COM 			    ":error(%d)", ret);
28757836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
28767836SJohn.Forte@Sun.COM 			break;
28777836SJohn.Forte@Sun.COM 	}
28787836SJohn.Forte@Sun.COM 
28797836SJohn.Forte@Sun.COM done:
28807836SJohn.Forte@Sun.COM 	(void) close(fd);
28817836SJohn.Forte@Sun.COM 	return (ret);
28827836SJohn.Forte@Sun.COM }
28837836SJohn.Forte@Sun.COM 
28847836SJohn.Forte@Sun.COM /*
28857836SJohn.Forte@Sun.COM  * stmfDevidFromIscsiName
28867836SJohn.Forte@Sun.COM  *
28877836SJohn.Forte@Sun.COM  * Purpose: convert an iSCSI name to an stmf devid
28887836SJohn.Forte@Sun.COM  *
28897836SJohn.Forte@Sun.COM  * iscsiName - unicode nul terminated utf-8 encoded iSCSI name
28907836SJohn.Forte@Sun.COM  * devid - on success, contains the converted iscsi name
28917836SJohn.Forte@Sun.COM  */
28927836SJohn.Forte@Sun.COM int
28937836SJohn.Forte@Sun.COM stmfDevidFromIscsiName(char *iscsiName, stmfDevid *devid)
28947836SJohn.Forte@Sun.COM {
28957836SJohn.Forte@Sun.COM 	if (devid == NULL || iscsiName == NULL)
28967836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
28977836SJohn.Forte@Sun.COM 
28987836SJohn.Forte@Sun.COM 	bzero(devid, sizeof (stmfDevid));
28997836SJohn.Forte@Sun.COM 
29007836SJohn.Forte@Sun.COM 	/* Validate size of target */
29017836SJohn.Forte@Sun.COM 	if ((devid->identLength = strlen(iscsiName)) > MAX_ISCSI_NAME ||
29027836SJohn.Forte@Sun.COM 	    devid->identLength < strlen(EUI) ||
29037836SJohn.Forte@Sun.COM 	    devid->identLength < strlen(IQN)) {
29047836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
29057836SJohn.Forte@Sun.COM 	}
29067836SJohn.Forte@Sun.COM 
29077836SJohn.Forte@Sun.COM 	if ((strncmp(iscsiName, EUI, strlen(EUI)) != 0) &&
29087836SJohn.Forte@Sun.COM 	    strncmp(iscsiName, IQN, strlen(IQN)) != 0) {
29097836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
29107836SJohn.Forte@Sun.COM 	}
29117836SJohn.Forte@Sun.COM 
29127836SJohn.Forte@Sun.COM 	/* copy UTF-8 bytes to ident */
29137836SJohn.Forte@Sun.COM 	bcopy(iscsiName, devid->ident, devid->identLength);
29147836SJohn.Forte@Sun.COM 
29157836SJohn.Forte@Sun.COM 	return (STMF_STATUS_SUCCESS);
29167836SJohn.Forte@Sun.COM }
29177836SJohn.Forte@Sun.COM 
29187836SJohn.Forte@Sun.COM /*
29197836SJohn.Forte@Sun.COM  * stmfDevidFromWwn
29207836SJohn.Forte@Sun.COM  *
29217836SJohn.Forte@Sun.COM  * Purpose: convert a WWN to an stmf devid
29227836SJohn.Forte@Sun.COM  *
29237836SJohn.Forte@Sun.COM  * wwn - 8-byte wwn identifier
29247836SJohn.Forte@Sun.COM  * devid - on success, contains the converted wwn
29257836SJohn.Forte@Sun.COM  */
29267836SJohn.Forte@Sun.COM int
29277836SJohn.Forte@Sun.COM stmfDevidFromWwn(uchar_t *wwn, stmfDevid *devid)
29287836SJohn.Forte@Sun.COM {
29297836SJohn.Forte@Sun.COM 	if (wwn == NULL || devid == NULL)
29307836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
29317836SJohn.Forte@Sun.COM 
29327836SJohn.Forte@Sun.COM 	bzero(devid, sizeof (stmfDevid));
29337836SJohn.Forte@Sun.COM 
29347836SJohn.Forte@Sun.COM 	/* Copy eui prefix */
29357836SJohn.Forte@Sun.COM 	(void) bcopy(WWN, devid->ident, strlen(WWN));
29367836SJohn.Forte@Sun.COM 
29377836SJohn.Forte@Sun.COM 	/* Convert to ASCII uppercase hexadecimal string */
29387836SJohn.Forte@Sun.COM 	(void) snprintf((char *)&devid->ident[strlen(WWN)],
29397836SJohn.Forte@Sun.COM 	    sizeof (devid->ident), "%02X%02X%02X%02X%02X%02X%02X%02X",
29407836SJohn.Forte@Sun.COM 	    wwn[0], wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]);
29417836SJohn.Forte@Sun.COM 
29427836SJohn.Forte@Sun.COM 	devid->identLength = strlen((char *)devid->ident);
29437836SJohn.Forte@Sun.COM 
29447836SJohn.Forte@Sun.COM 	return (STMF_STATUS_SUCCESS);
29457836SJohn.Forte@Sun.COM }
29467836SJohn.Forte@Sun.COM 
29477836SJohn.Forte@Sun.COM /*
29487836SJohn.Forte@Sun.COM  * stmfFreeMemory
29497836SJohn.Forte@Sun.COM  *
29507836SJohn.Forte@Sun.COM  * Purpose: Free memory allocated by this library
29517836SJohn.Forte@Sun.COM  *
29527836SJohn.Forte@Sun.COM  * memory - previously allocated pointer of memory managed by library
29537836SJohn.Forte@Sun.COM  */
29547836SJohn.Forte@Sun.COM void
29557836SJohn.Forte@Sun.COM stmfFreeMemory(void *memory)
29567836SJohn.Forte@Sun.COM {
29577836SJohn.Forte@Sun.COM 	free(memory);
29587836SJohn.Forte@Sun.COM }
29597836SJohn.Forte@Sun.COM 
29607836SJohn.Forte@Sun.COM /*
2961*9585STim.Szeto@Sun.COM  * get host group, target group list from stmf
29627836SJohn.Forte@Sun.COM  *
2963*9585STim.Szeto@Sun.COM  * groupType - HOST_GROUP, TARGET_GROUP
29647836SJohn.Forte@Sun.COM  */
2965*9585STim.Szeto@Sun.COM static int
2966*9585STim.Szeto@Sun.COM groupListIoctl(stmfGroupList **groupList, int groupType)
2967*9585STim.Szeto@Sun.COM {
2968*9585STim.Szeto@Sun.COM 	int ret;
2969*9585STim.Szeto@Sun.COM 	int fd;
2970*9585STim.Szeto@Sun.COM 	int ioctlRet;
2971*9585STim.Szeto@Sun.COM 	int i;
2972*9585STim.Szeto@Sun.COM 	int cmd;
2973*9585STim.Szeto@Sun.COM 	stmf_iocdata_t stmfIoctl;
2974*9585STim.Szeto@Sun.COM 	/* framework group list */
2975*9585STim.Szeto@Sun.COM 	stmf_group_name_t *iGroupList = NULL;
2976*9585STim.Szeto@Sun.COM 	uint32_t groupListSize;
2977*9585STim.Szeto@Sun.COM 
2978*9585STim.Szeto@Sun.COM 	if (groupList == NULL) {
2979*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
2980*9585STim.Szeto@Sun.COM 	}
2981*9585STim.Szeto@Sun.COM 
2982*9585STim.Szeto@Sun.COM 	if (groupType == HOST_GROUP) {
2983*9585STim.Szeto@Sun.COM 		cmd = STMF_IOCTL_GET_HG_LIST;
2984*9585STim.Szeto@Sun.COM 	} else if (groupType == TARGET_GROUP) {
2985*9585STim.Szeto@Sun.COM 		cmd = STMF_IOCTL_GET_TG_LIST;
2986*9585STim.Szeto@Sun.COM 	} else {
2987*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
2988*9585STim.Szeto@Sun.COM 	}
2989*9585STim.Szeto@Sun.COM 
2990*9585STim.Szeto@Sun.COM 	/* call init */
2991*9585STim.Szeto@Sun.COM 	ret = initializeConfig();
2992*9585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
2993*9585STim.Szeto@Sun.COM 		return (ret);
2994*9585STim.Szeto@Sun.COM 	}
2995*9585STim.Szeto@Sun.COM 
2996*9585STim.Szeto@Sun.COM 	/*
2997*9585STim.Szeto@Sun.COM 	 * Open control node for stmf
2998*9585STim.Szeto@Sun.COM 	 */
2999*9585STim.Szeto@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
3000*9585STim.Szeto@Sun.COM 		return (ret);
3001*9585STim.Szeto@Sun.COM 
3002*9585STim.Szeto@Sun.COM 	/*
3003*9585STim.Szeto@Sun.COM 	 * Allocate ioctl input buffer
3004*9585STim.Szeto@Sun.COM 	 */
3005*9585STim.Szeto@Sun.COM 	groupListSize = ALLOC_GROUP;
3006*9585STim.Szeto@Sun.COM 	groupListSize = groupListSize * (sizeof (stmf_group_name_t));
3007*9585STim.Szeto@Sun.COM 	iGroupList = (stmf_group_name_t *)calloc(1, groupListSize);
3008*9585STim.Szeto@Sun.COM 	if (iGroupList == NULL) {
3009*9585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
3010*9585STim.Szeto@Sun.COM 		goto done;
3011*9585STim.Szeto@Sun.COM 	}
3012*9585STim.Szeto@Sun.COM 
3013*9585STim.Szeto@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
3014*9585STim.Szeto@Sun.COM 	/*
3015*9585STim.Szeto@Sun.COM 	 * Issue ioctl to get the group list
3016*9585STim.Szeto@Sun.COM 	 */
3017*9585STim.Szeto@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
3018*9585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf_size = groupListSize;
3019*9585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupList;
3020*9585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
3021*9585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
3022*9585STim.Szeto@Sun.COM 		switch (errno) {
3023*9585STim.Szeto@Sun.COM 			case EBUSY:
3024*9585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
3025*9585STim.Szeto@Sun.COM 				break;
3026*9585STim.Szeto@Sun.COM 			case EPERM:
3027*9585STim.Szeto@Sun.COM 			case EACCES:
3028*9585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
3029*9585STim.Szeto@Sun.COM 				break;
3030*9585STim.Szeto@Sun.COM 			default:
3031*9585STim.Szeto@Sun.COM 				syslog(LOG_DEBUG,
3032*9585STim.Szeto@Sun.COM 				    "groupListIoctl:ioctl errno(%d)",
3033*9585STim.Szeto@Sun.COM 				    errno);
3034*9585STim.Szeto@Sun.COM 				ret = STMF_STATUS_ERROR;
3035*9585STim.Szeto@Sun.COM 				break;
3036*9585STim.Szeto@Sun.COM 		}
3037*9585STim.Szeto@Sun.COM 		goto done;
3038*9585STim.Szeto@Sun.COM 	}
3039*9585STim.Szeto@Sun.COM 	/*
3040*9585STim.Szeto@Sun.COM 	 * Check whether input buffer was large enough
3041*9585STim.Szeto@Sun.COM 	 */
3042*9585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_GROUP) {
3043*9585STim.Szeto@Sun.COM 		groupListSize = stmfIoctl.stmf_obuf_max_nentries *
3044*9585STim.Szeto@Sun.COM 		    sizeof (stmf_group_name_t);
3045*9585STim.Szeto@Sun.COM 		iGroupList = realloc(iGroupList, groupListSize);
3046*9585STim.Szeto@Sun.COM 		if (iGroupList == NULL) {
3047*9585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NOMEM;
3048*9585STim.Szeto@Sun.COM 			goto done;
3049*9585STim.Szeto@Sun.COM 		}
3050*9585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf_size = groupListSize;
3051*9585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupList;
3052*9585STim.Szeto@Sun.COM 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
3053*9585STim.Szeto@Sun.COM 		if (ioctlRet != 0) {
3054*9585STim.Szeto@Sun.COM 			switch (errno) {
3055*9585STim.Szeto@Sun.COM 				case EBUSY:
3056*9585STim.Szeto@Sun.COM 					ret = STMF_ERROR_BUSY;
3057*9585STim.Szeto@Sun.COM 					break;
3058*9585STim.Szeto@Sun.COM 				case EPERM:
3059*9585STim.Szeto@Sun.COM 				case EACCES:
3060*9585STim.Szeto@Sun.COM 					ret = STMF_ERROR_PERM;
3061*9585STim.Szeto@Sun.COM 					break;
3062*9585STim.Szeto@Sun.COM 				default:
3063*9585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
3064*9585STim.Szeto@Sun.COM 					    "groupListIoctl:ioctl errno(%d)",
3065*9585STim.Szeto@Sun.COM 					    errno);
3066*9585STim.Szeto@Sun.COM 					ret = STMF_STATUS_ERROR;
3067*9585STim.Szeto@Sun.COM 					break;
3068*9585STim.Szeto@Sun.COM 			}
3069*9585STim.Szeto@Sun.COM 			goto done;
3070*9585STim.Szeto@Sun.COM 		}
3071*9585STim.Szeto@Sun.COM 	}
3072*9585STim.Szeto@Sun.COM 
3073*9585STim.Szeto@Sun.COM 	/* allocate and copy to caller's buffer */
3074*9585STim.Szeto@Sun.COM 	*groupList = (stmfGroupList *)calloc(1, sizeof (stmfGroupList) *
3075*9585STim.Szeto@Sun.COM 	    stmfIoctl.stmf_obuf_nentries);
3076*9585STim.Szeto@Sun.COM 	if (*groupList == NULL) {
3077*9585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
3078*9585STim.Szeto@Sun.COM 		goto done;
3079*9585STim.Szeto@Sun.COM 	}
3080*9585STim.Szeto@Sun.COM 	(*groupList)->cnt = stmfIoctl.stmf_obuf_nentries;
3081*9585STim.Szeto@Sun.COM 	for (i = 0; i < stmfIoctl.stmf_obuf_nentries; i++) {
3082*9585STim.Szeto@Sun.COM 		bcopy(iGroupList->name, (*groupList)->name[i],
3083*9585STim.Szeto@Sun.COM 		    sizeof (stmfGroupName));
3084*9585STim.Szeto@Sun.COM 		iGroupList++;
3085*9585STim.Szeto@Sun.COM 	}
3086*9585STim.Szeto@Sun.COM 
3087*9585STim.Szeto@Sun.COM done:
3088*9585STim.Szeto@Sun.COM 	free(iGroupList);
3089*9585STim.Szeto@Sun.COM 	(void) close(fd);
3090*9585STim.Szeto@Sun.COM 	return (ret);
3091*9585STim.Szeto@Sun.COM }
3092*9585STim.Szeto@Sun.COM 
3093*9585STim.Szeto@Sun.COM /*
3094*9585STim.Szeto@Sun.COM  * get host group members, target group members from stmf
3095*9585STim.Szeto@Sun.COM  *
3096*9585STim.Szeto@Sun.COM  * groupProps - allocated on success
3097*9585STim.Szeto@Sun.COM  *
3098*9585STim.Szeto@Sun.COM  * groupType - HOST_GROUP, TARGET_GROUP
3099*9585STim.Szeto@Sun.COM  */
3100*9585STim.Szeto@Sun.COM static int
3101*9585STim.Szeto@Sun.COM groupMemberListIoctl(stmfGroupName *groupName, stmfGroupProperties **groupProps,
3102*9585STim.Szeto@Sun.COM     int groupType)
31037836SJohn.Forte@Sun.COM {
31047836SJohn.Forte@Sun.COM 	int ret;
3105*9585STim.Szeto@Sun.COM 	int fd;
3106*9585STim.Szeto@Sun.COM 	int ioctlRet;
3107*9585STim.Szeto@Sun.COM 	int i;
3108*9585STim.Szeto@Sun.COM 	int cmd;
3109*9585STim.Szeto@Sun.COM 	stmf_iocdata_t stmfIoctl;
3110*9585STim.Szeto@Sun.COM 	/* framework group list */
3111*9585STim.Szeto@Sun.COM 	stmf_group_name_t iGroupName;
3112*9585STim.Szeto@Sun.COM 	stmf_ge_ident_t *iGroupMembers;
3113*9585STim.Szeto@Sun.COM 	uint32_t groupListSize;
3114*9585STim.Szeto@Sun.COM 
3115*9585STim.Szeto@Sun.COM 	if (groupName == NULL) {
3116*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
3117*9585STim.Szeto@Sun.COM 	}
3118*9585STim.Szeto@Sun.COM 
3119*9585STim.Szeto@Sun.COM 	if (groupType == HOST_GROUP) {
3120*9585STim.Szeto@Sun.COM 		cmd = STMF_IOCTL_GET_HG_ENTRIES;
3121*9585STim.Szeto@Sun.COM 	} else if (groupType == TARGET_GROUP) {
3122*9585STim.Szeto@Sun.COM 		cmd = STMF_IOCTL_GET_TG_ENTRIES;
3123*9585STim.Szeto@Sun.COM 	} else {
31247836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
31257836SJohn.Forte@Sun.COM 	}
31267836SJohn.Forte@Sun.COM 
3127*9585STim.Szeto@Sun.COM 	/* call init */
3128*9585STim.Szeto@Sun.COM 	ret = initializeConfig();
3129*9585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
3130*9585STim.Szeto@Sun.COM 		return (ret);
3131*9585STim.Szeto@Sun.COM 	}
3132*9585STim.Szeto@Sun.COM 
3133*9585STim.Szeto@Sun.COM 	/*
3134*9585STim.Szeto@Sun.COM 	 * Open control node for stmf
3135*9585STim.Szeto@Sun.COM 	 */
3136*9585STim.Szeto@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
3137*9585STim.Szeto@Sun.COM 		return (ret);
3138*9585STim.Szeto@Sun.COM 
3139*9585STim.Szeto@Sun.COM 	bzero(&iGroupName, sizeof (iGroupName));
3140*9585STim.Szeto@Sun.COM 
3141*9585STim.Szeto@Sun.COM 	bcopy(groupName, &iGroupName.name, strlen((char *)groupName));
3142*9585STim.Szeto@Sun.COM 
3143*9585STim.Szeto@Sun.COM 	iGroupName.name_size = strlen((char *)groupName);
3144*9585STim.Szeto@Sun.COM 
3145*9585STim.Szeto@Sun.COM 	/*
3146*9585STim.Szeto@Sun.COM 	 * Allocate ioctl input buffer
3147*9585STim.Szeto@Sun.COM 	 */
3148*9585STim.Szeto@Sun.COM 	groupListSize = ALLOC_GRP_MEMBER;
3149*9585STim.Szeto@Sun.COM 	groupListSize = groupListSize * (sizeof (stmf_ge_ident_t));
3150*9585STim.Szeto@Sun.COM 	iGroupMembers = (stmf_ge_ident_t *)calloc(1, groupListSize);
3151*9585STim.Szeto@Sun.COM 	if (iGroupMembers == NULL) {
3152*9585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
3153*9585STim.Szeto@Sun.COM 		goto done;
3154*9585STim.Szeto@Sun.COM 	}
3155*9585STim.Szeto@Sun.COM 
3156*9585STim.Szeto@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
3157*9585STim.Szeto@Sun.COM 	/*
3158*9585STim.Szeto@Sun.COM 	 * Issue ioctl to get the group list
3159*9585STim.Szeto@Sun.COM 	 */
3160*9585STim.Szeto@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
3161*9585STim.Szeto@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&iGroupName;
3162*9585STim.Szeto@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (stmf_group_name_t);
3163*9585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf_size = groupListSize;
3164*9585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupMembers;
3165*9585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
3166*9585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
3167*9585STim.Szeto@Sun.COM 		switch (errno) {
3168*9585STim.Szeto@Sun.COM 			case EBUSY:
3169*9585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
3170*9585STim.Szeto@Sun.COM 				break;
3171*9585STim.Szeto@Sun.COM 			case EPERM:
3172*9585STim.Szeto@Sun.COM 			case EACCES:
3173*9585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
3174*9585STim.Szeto@Sun.COM 				break;
3175*9585STim.Szeto@Sun.COM 			default:
3176*9585STim.Szeto@Sun.COM 				syslog(LOG_DEBUG,
3177*9585STim.Szeto@Sun.COM 				    "groupListIoctl:ioctl errno(%d)",
3178*9585STim.Szeto@Sun.COM 				    errno);
3179*9585STim.Szeto@Sun.COM 				ret = STMF_STATUS_ERROR;
3180*9585STim.Szeto@Sun.COM 				break;
3181*9585STim.Szeto@Sun.COM 		}
3182*9585STim.Szeto@Sun.COM 		goto done;
3183*9585STim.Szeto@Sun.COM 	}
3184*9585STim.Szeto@Sun.COM 	/*
3185*9585STim.Szeto@Sun.COM 	 * Check whether input buffer was large enough
3186*9585STim.Szeto@Sun.COM 	 */
3187*9585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_GRP_MEMBER) {
3188*9585STim.Szeto@Sun.COM 		groupListSize = stmfIoctl.stmf_obuf_max_nentries *
3189*9585STim.Szeto@Sun.COM 		    sizeof (stmf_ge_ident_t);
3190*9585STim.Szeto@Sun.COM 		iGroupMembers = realloc(iGroupMembers, groupListSize);
3191*9585STim.Szeto@Sun.COM 		if (iGroupMembers == NULL) {
3192*9585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NOMEM;
3193*9585STim.Szeto@Sun.COM 			goto done;
3194*9585STim.Szeto@Sun.COM 		}
3195*9585STim.Szeto@Sun.COM 		stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&iGroupName;
3196*9585STim.Szeto@Sun.COM 		stmfIoctl.stmf_ibuf_size = sizeof (stmf_group_name_t);
3197*9585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf_size = groupListSize;
3198*9585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupMembers;
3199*9585STim.Szeto@Sun.COM 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
3200*9585STim.Szeto@Sun.COM 		if (ioctlRet != 0) {
3201*9585STim.Szeto@Sun.COM 			switch (errno) {
3202*9585STim.Szeto@Sun.COM 				case EBUSY:
3203*9585STim.Szeto@Sun.COM 					ret = STMF_ERROR_BUSY;
3204*9585STim.Szeto@Sun.COM 					break;
3205*9585STim.Szeto@Sun.COM 				case EPERM:
3206*9585STim.Szeto@Sun.COM 				case EACCES:
3207*9585STim.Szeto@Sun.COM 					ret = STMF_ERROR_PERM;
3208*9585STim.Szeto@Sun.COM 					break;
3209*9585STim.Szeto@Sun.COM 				default:
3210*9585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
3211*9585STim.Szeto@Sun.COM 					    "groupListIoctl:ioctl errno(%d)",
3212*9585STim.Szeto@Sun.COM 					    errno);
3213*9585STim.Szeto@Sun.COM 					ret = STMF_STATUS_ERROR;
3214*9585STim.Szeto@Sun.COM 					break;
3215*9585STim.Szeto@Sun.COM 			}
3216*9585STim.Szeto@Sun.COM 			goto done;
3217*9585STim.Szeto@Sun.COM 		}
3218*9585STim.Szeto@Sun.COM 	}
3219*9585STim.Szeto@Sun.COM 
3220*9585STim.Szeto@Sun.COM 	/* allocate and copy to caller's buffer */
3221*9585STim.Szeto@Sun.COM 	*groupProps = (stmfGroupProperties *)calloc(1,
3222*9585STim.Szeto@Sun.COM 	    sizeof (stmfGroupProperties) * stmfIoctl.stmf_obuf_nentries);
3223*9585STim.Szeto@Sun.COM 	if (*groupProps == NULL) {
3224*9585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
3225*9585STim.Szeto@Sun.COM 		goto done;
3226*9585STim.Szeto@Sun.COM 	}
3227*9585STim.Szeto@Sun.COM 	(*groupProps)->cnt = stmfIoctl.stmf_obuf_nentries;
3228*9585STim.Szeto@Sun.COM 	for (i = 0; i < stmfIoctl.stmf_obuf_nentries; i++) {
3229*9585STim.Szeto@Sun.COM 		(*groupProps)->name[i].identLength =
3230*9585STim.Szeto@Sun.COM 		    iGroupMembers->ident_size;
3231*9585STim.Szeto@Sun.COM 		bcopy(iGroupMembers->ident, (*groupProps)->name[i].ident,
3232*9585STim.Szeto@Sun.COM 		    iGroupMembers->ident_size);
3233*9585STim.Szeto@Sun.COM 		iGroupMembers++;
3234*9585STim.Szeto@Sun.COM 	}
3235*9585STim.Szeto@Sun.COM 
3236*9585STim.Szeto@Sun.COM done:
3237*9585STim.Szeto@Sun.COM 	free(iGroupMembers);
3238*9585STim.Szeto@Sun.COM 	(void) close(fd);
3239*9585STim.Szeto@Sun.COM 	return (ret);
3240*9585STim.Szeto@Sun.COM }
3241*9585STim.Szeto@Sun.COM 
3242*9585STim.Szeto@Sun.COM /*
3243*9585STim.Szeto@Sun.COM  * Purpose: access persistent config data for host groups and target groups
3244*9585STim.Szeto@Sun.COM  */
3245*9585STim.Szeto@Sun.COM static int
3246*9585STim.Szeto@Sun.COM iLoadGroupFromPs(stmfGroupList **groupList, int type)
3247*9585STim.Szeto@Sun.COM {
3248*9585STim.Szeto@Sun.COM 	int ret;
3249*9585STim.Szeto@Sun.COM 
3250*9585STim.Szeto@Sun.COM 	if (groupList == NULL) {
3251*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
3252*9585STim.Szeto@Sun.COM 	}
3253*9585STim.Szeto@Sun.COM 
3254*9585STim.Szeto@Sun.COM 	if (type == HOST_GROUP) {
3255*9585STim.Szeto@Sun.COM 		ret = psGetHostGroupList(groupList);
3256*9585STim.Szeto@Sun.COM 	} else if (type == TARGET_GROUP) {
3257*9585STim.Szeto@Sun.COM 		ret = psGetTargetGroupList(groupList);
3258*9585STim.Szeto@Sun.COM 	} else {
3259*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
3260*9585STim.Szeto@Sun.COM 	}
32617836SJohn.Forte@Sun.COM 	switch (ret) {
32627836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
32637836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
32647836SJohn.Forte@Sun.COM 			break;
32657836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
32667836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
32677836SJohn.Forte@Sun.COM 			break;
32687836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
32697836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
32707836SJohn.Forte@Sun.COM 			break;
32717836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
32727836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
32737836SJohn.Forte@Sun.COM 			break;
32747836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
32757836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
32767836SJohn.Forte@Sun.COM 			break;
32777836SJohn.Forte@Sun.COM 		default:
32787836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
32797836SJohn.Forte@Sun.COM 			    "stmfGetHostGroupList:psGetHostGroupList:error(%d)",
32807836SJohn.Forte@Sun.COM 			    ret);
32817836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
32827836SJohn.Forte@Sun.COM 			break;
32837836SJohn.Forte@Sun.COM 	}
32847836SJohn.Forte@Sun.COM 
32857836SJohn.Forte@Sun.COM 	return (ret);
32867836SJohn.Forte@Sun.COM }
32877836SJohn.Forte@Sun.COM 
32887836SJohn.Forte@Sun.COM /*
3289*9585STim.Szeto@Sun.COM  * stmfGetHostGroupList
32907836SJohn.Forte@Sun.COM  *
3291*9585STim.Szeto@Sun.COM  * Purpose: Retrieves the list of initiator group oids
3292*9585STim.Szeto@Sun.COM  *
3293*9585STim.Szeto@Sun.COM  * hostGroupList - pointer to pointer to hostGroupList structure
3294*9585STim.Szeto@Sun.COM  *                 on success, this contains the host group list.
32957836SJohn.Forte@Sun.COM  */
32967836SJohn.Forte@Sun.COM int
3297*9585STim.Szeto@Sun.COM stmfGetHostGroupList(stmfGroupList **hostGroupList)
3298*9585STim.Szeto@Sun.COM {
3299*9585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_ERROR;
3300*9585STim.Szeto@Sun.COM 
3301*9585STim.Szeto@Sun.COM 	if (hostGroupList == NULL) {
3302*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
3303*9585STim.Szeto@Sun.COM 	}
3304*9585STim.Szeto@Sun.COM 
3305*9585STim.Szeto@Sun.COM 	ret = groupListIoctl(hostGroupList, HOST_GROUP);
3306*9585STim.Szeto@Sun.COM 	return (ret);
3307*9585STim.Szeto@Sun.COM }
3308*9585STim.Szeto@Sun.COM 
3309*9585STim.Szeto@Sun.COM 
3310*9585STim.Szeto@Sun.COM /*
3311*9585STim.Szeto@Sun.COM  * Purpose: access persistent config data for host groups and target groups
3312*9585STim.Szeto@Sun.COM  */
3313*9585STim.Szeto@Sun.COM static int
3314*9585STim.Szeto@Sun.COM iLoadGroupMembersFromPs(stmfGroupName *groupName,
3315*9585STim.Szeto@Sun.COM     stmfGroupProperties **groupProp, int type)
33167836SJohn.Forte@Sun.COM {
33177836SJohn.Forte@Sun.COM 	int ret;
33187836SJohn.Forte@Sun.COM 
3319*9585STim.Szeto@Sun.COM 	if (groupName == NULL) {
33207836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
33217836SJohn.Forte@Sun.COM 	}
33227836SJohn.Forte@Sun.COM 
3323*9585STim.Szeto@Sun.COM 	if (type == HOST_GROUP) {
3324*9585STim.Szeto@Sun.COM 		ret = psGetHostGroupMemberList((char *)groupName, groupProp);
3325*9585STim.Szeto@Sun.COM 	} else if (type == TARGET_GROUP) {
3326*9585STim.Szeto@Sun.COM 		ret = psGetTargetGroupMemberList((char *)groupName, groupProp);
3327*9585STim.Szeto@Sun.COM 	} else {
3328*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
3329*9585STim.Szeto@Sun.COM 	}
33307836SJohn.Forte@Sun.COM 	switch (ret) {
33317836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
33327836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
33337836SJohn.Forte@Sun.COM 			break;
33347836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
33357836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
33367836SJohn.Forte@Sun.COM 			break;
33377836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
33387836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
33397836SJohn.Forte@Sun.COM 			break;
33407836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
33417836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
33427836SJohn.Forte@Sun.COM 			break;
33437836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
33447836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
33457836SJohn.Forte@Sun.COM 			break;
33467836SJohn.Forte@Sun.COM 		default:
33477836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
3348*9585STim.Szeto@Sun.COM 			    "iLoadGroupMembersFromPs:psGetHostGroupList:"
3349*9585STim.Szeto@Sun.COM 			    "error(%d)", ret);
33507836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
33517836SJohn.Forte@Sun.COM 			break;
33527836SJohn.Forte@Sun.COM 	}
33537836SJohn.Forte@Sun.COM 
33547836SJohn.Forte@Sun.COM 	return (ret);
33557836SJohn.Forte@Sun.COM }
33567836SJohn.Forte@Sun.COM 
33577836SJohn.Forte@Sun.COM /*
3358*9585STim.Szeto@Sun.COM  * stmfGetHostGroupMembers
3359*9585STim.Szeto@Sun.COM  *
3360*9585STim.Szeto@Sun.COM  * Purpose: Retrieves the group properties for a host group
3361*9585STim.Szeto@Sun.COM  *
3362*9585STim.Szeto@Sun.COM  * groupName - name of group for which to retrieve host group members.
3363*9585STim.Szeto@Sun.COM  * groupProp - pointer to pointer to stmfGroupProperties structure
3364*9585STim.Szeto@Sun.COM  *             on success, this contains the list of group members.
3365*9585STim.Szeto@Sun.COM  */
3366*9585STim.Szeto@Sun.COM int
3367*9585STim.Szeto@Sun.COM stmfGetHostGroupMembers(stmfGroupName *groupName,
3368*9585STim.Szeto@Sun.COM     stmfGroupProperties **groupProp)
3369*9585STim.Szeto@Sun.COM {
3370*9585STim.Szeto@Sun.COM 	int ret;
3371*9585STim.Szeto@Sun.COM 
3372*9585STim.Szeto@Sun.COM 	if (groupName == NULL || groupProp == NULL) {
3373*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
3374*9585STim.Szeto@Sun.COM 	}
3375*9585STim.Szeto@Sun.COM 
3376*9585STim.Szeto@Sun.COM 	ret = groupMemberListIoctl(groupName, groupProp, HOST_GROUP);
3377*9585STim.Szeto@Sun.COM 
3378*9585STim.Szeto@Sun.COM 	return (ret);
3379*9585STim.Szeto@Sun.COM }
3380*9585STim.Szeto@Sun.COM 
3381*9585STim.Szeto@Sun.COM /*
33827836SJohn.Forte@Sun.COM  * stmfGetProviderData
33837836SJohn.Forte@Sun.COM  *
33847836SJohn.Forte@Sun.COM  * Purpose: Get provider data list
33857836SJohn.Forte@Sun.COM  *
33867836SJohn.Forte@Sun.COM  * providerName - name of provider for which to retrieve the data
33877836SJohn.Forte@Sun.COM  * nvl - pointer to nvlist_t pointer which will contain the nvlist data
33887836SJohn.Forte@Sun.COM  *       retrieved.
33897836SJohn.Forte@Sun.COM  * providerType - type of provider for which to retrieve data.
33907836SJohn.Forte@Sun.COM  *		    STMF_LU_PROVIDER_TYPE
33917836SJohn.Forte@Sun.COM  *		    STMF_PORT_PROVIDER_TYPE
33927836SJohn.Forte@Sun.COM  */
33937836SJohn.Forte@Sun.COM int
33947836SJohn.Forte@Sun.COM stmfGetProviderData(char *providerName, nvlist_t **nvl, int providerType)
33957836SJohn.Forte@Sun.COM {
33967836SJohn.Forte@Sun.COM 	return (stmfGetProviderDataProt(providerName, nvl, providerType,
33977836SJohn.Forte@Sun.COM 	    NULL));
33987836SJohn.Forte@Sun.COM }
33997836SJohn.Forte@Sun.COM 
34007836SJohn.Forte@Sun.COM /*
34017836SJohn.Forte@Sun.COM  * stmfGetProviderDataProt
34027836SJohn.Forte@Sun.COM  *
34037836SJohn.Forte@Sun.COM  * Purpose: Get provider data list with token
34047836SJohn.Forte@Sun.COM  *
34057836SJohn.Forte@Sun.COM  * providerName - name of provider for which to retrieve the data
34067836SJohn.Forte@Sun.COM  * nvl - pointer to nvlist_t pointer which will contain the nvlist data
34077836SJohn.Forte@Sun.COM  *       retrieved.
34087836SJohn.Forte@Sun.COM  * providerType - type of provider for which to retrieve data.
34097836SJohn.Forte@Sun.COM  *		    STMF_LU_PROVIDER_TYPE
34107836SJohn.Forte@Sun.COM  *		    STMF_PORT_PROVIDER_TYPE
34117836SJohn.Forte@Sun.COM  * setToken - Returns the stale data token
34127836SJohn.Forte@Sun.COM  */
34137836SJohn.Forte@Sun.COM int
34147836SJohn.Forte@Sun.COM stmfGetProviderDataProt(char *providerName, nvlist_t **nvl, int providerType,
34157836SJohn.Forte@Sun.COM     uint64_t *setToken)
34167836SJohn.Forte@Sun.COM {
34177836SJohn.Forte@Sun.COM 	int ret;
34187836SJohn.Forte@Sun.COM 
34197836SJohn.Forte@Sun.COM 	if (providerName == NULL || nvl == NULL) {
34207836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
34217836SJohn.Forte@Sun.COM 	}
34227836SJohn.Forte@Sun.COM 	if (providerType != STMF_LU_PROVIDER_TYPE &&
34237836SJohn.Forte@Sun.COM 	    providerType != STMF_PORT_PROVIDER_TYPE) {
34247836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
34257836SJohn.Forte@Sun.COM 	}
34267836SJohn.Forte@Sun.COM 	/* call init */
34277836SJohn.Forte@Sun.COM 	ret = initializeConfig();
34287836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
34297836SJohn.Forte@Sun.COM 		return (ret);
34307836SJohn.Forte@Sun.COM 	}
3431*9585STim.Szeto@Sun.COM 	return (getProviderData(providerName, nvl, providerType, setToken));
34327836SJohn.Forte@Sun.COM }
34337836SJohn.Forte@Sun.COM 
34347836SJohn.Forte@Sun.COM /*
34357836SJohn.Forte@Sun.COM  * stmfGetProviderDataList
34367836SJohn.Forte@Sun.COM  *
34377836SJohn.Forte@Sun.COM  * Purpose: Get the list of providers currently persisting data
34387836SJohn.Forte@Sun.COM  *
34397836SJohn.Forte@Sun.COM  * providerList - pointer to pointer to an stmfProviderList structure allocated
34407836SJohn.Forte@Sun.COM  *                by the caller. Will contain the list of providers on success.
34417836SJohn.Forte@Sun.COM  */
34427836SJohn.Forte@Sun.COM int
34437836SJohn.Forte@Sun.COM stmfGetProviderDataList(stmfProviderList **providerList)
34447836SJohn.Forte@Sun.COM {
34457836SJohn.Forte@Sun.COM 	int ret;
34467836SJohn.Forte@Sun.COM 
34477836SJohn.Forte@Sun.COM 	ret = psGetProviderDataList(providerList);
34487836SJohn.Forte@Sun.COM 	switch (ret) {
34497836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
34507836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
34517836SJohn.Forte@Sun.COM 			break;
34527836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
34537836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
34547836SJohn.Forte@Sun.COM 			break;
34557836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
34567836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
34577836SJohn.Forte@Sun.COM 			break;
34587836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
34597836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
34607836SJohn.Forte@Sun.COM 			break;
34617836SJohn.Forte@Sun.COM 		default:
34627836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
34637836SJohn.Forte@Sun.COM 			    "stmfGetProviderDataList:psGetProviderDataList"
34647836SJohn.Forte@Sun.COM 			    ":error(%d)", ret);
34657836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
34667836SJohn.Forte@Sun.COM 			break;
34677836SJohn.Forte@Sun.COM 	}
34687836SJohn.Forte@Sun.COM 
34697836SJohn.Forte@Sun.COM 	return (ret);
34707836SJohn.Forte@Sun.COM }
34717836SJohn.Forte@Sun.COM 
34727836SJohn.Forte@Sun.COM 
34737836SJohn.Forte@Sun.COM /*
34747836SJohn.Forte@Sun.COM  * stmfGetSessionList
34757836SJohn.Forte@Sun.COM  *
34767836SJohn.Forte@Sun.COM  * Purpose: Retrieves the session list for a target (devid)
34777836SJohn.Forte@Sun.COM  *
34787836SJohn.Forte@Sun.COM  * devid - devid of target for which to retrieve session information.
34797836SJohn.Forte@Sun.COM  * sessionList - pointer to pointer to stmfSessionList structure
34807836SJohn.Forte@Sun.COM  *             on success, this contains the list of initiator sessions.
34817836SJohn.Forte@Sun.COM  */
34827836SJohn.Forte@Sun.COM int
34837836SJohn.Forte@Sun.COM stmfGetSessionList(stmfDevid *devid, stmfSessionList **sessionList)
34847836SJohn.Forte@Sun.COM {
34857836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
34867836SJohn.Forte@Sun.COM 	int fd;
34877836SJohn.Forte@Sun.COM 	int ioctlRet;
34887836SJohn.Forte@Sun.COM 	int cmd = STMF_IOCTL_SESSION_LIST;
34897836SJohn.Forte@Sun.COM 	int i;
34907836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
34917836SJohn.Forte@Sun.COM 	slist_scsi_session_t *fSessionList;
34927836SJohn.Forte@Sun.COM 	uint8_t ident[260];
34937836SJohn.Forte@Sun.COM 	uint32_t fSessionListSize;
34947836SJohn.Forte@Sun.COM 
34957836SJohn.Forte@Sun.COM 	if (sessionList == NULL || devid == NULL) {
34967836SJohn.Forte@Sun.COM 		ret = STMF_ERROR_INVALID_ARG;
34977836SJohn.Forte@Sun.COM 	}
34987836SJohn.Forte@Sun.COM 
34997836SJohn.Forte@Sun.COM 	/* call init */
35007836SJohn.Forte@Sun.COM 	ret = initializeConfig();
35017836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
35027836SJohn.Forte@Sun.COM 		return (ret);
35037836SJohn.Forte@Sun.COM 	}
35047836SJohn.Forte@Sun.COM 
35057836SJohn.Forte@Sun.COM 	/*
35067836SJohn.Forte@Sun.COM 	 * Open control node for stmf
35077836SJohn.Forte@Sun.COM 	 */
35087836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
35097836SJohn.Forte@Sun.COM 		return (ret);
35107836SJohn.Forte@Sun.COM 
35117836SJohn.Forte@Sun.COM 	/*
35127836SJohn.Forte@Sun.COM 	 * Allocate ioctl input buffer
35137836SJohn.Forte@Sun.COM 	 */
3514*9585STim.Szeto@Sun.COM 	fSessionListSize = ALLOC_SESSION;
35157836SJohn.Forte@Sun.COM 	fSessionListSize = fSessionListSize * (sizeof (slist_scsi_session_t));
35167836SJohn.Forte@Sun.COM 	fSessionList = (slist_scsi_session_t *)calloc(1, fSessionListSize);
35177836SJohn.Forte@Sun.COM 	if (fSessionList == NULL) {
35187836SJohn.Forte@Sun.COM 		return (STMF_ERROR_NOMEM);
35197836SJohn.Forte@Sun.COM 	}
35207836SJohn.Forte@Sun.COM 
35217836SJohn.Forte@Sun.COM 	ident[IDENT_LENGTH_BYTE] = devid->identLength;
35227836SJohn.Forte@Sun.COM 	bcopy(&(devid->ident), &ident[IDENT_LENGTH_BYTE + 1],
35237836SJohn.Forte@Sun.COM 	    devid->identLength);
35247836SJohn.Forte@Sun.COM 
35257836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
35267836SJohn.Forte@Sun.COM 	/*
35277836SJohn.Forte@Sun.COM 	 * Issue ioctl to get the session list
35287836SJohn.Forte@Sun.COM 	 */
35297836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
35307836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ident;
35317836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (ident);
35327836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = fSessionListSize;
35337836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fSessionList;
35347836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
35357836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
35367836SJohn.Forte@Sun.COM 		switch (errno) {
35377836SJohn.Forte@Sun.COM 			case EBUSY:
35387836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
35397836SJohn.Forte@Sun.COM 				break;
3540*9585STim.Szeto@Sun.COM 			case EPERM:
35417836SJohn.Forte@Sun.COM 			case EACCES:
35427836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
35437836SJohn.Forte@Sun.COM 				break;
35447836SJohn.Forte@Sun.COM 			default:
35457836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
35467836SJohn.Forte@Sun.COM 				    "stmfGetSessionList:ioctl errno(%d)",
35477836SJohn.Forte@Sun.COM 				    errno);
35487836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
35497836SJohn.Forte@Sun.COM 				break;
35507836SJohn.Forte@Sun.COM 		}
35517836SJohn.Forte@Sun.COM 		goto done;
35527836SJohn.Forte@Sun.COM 	}
35537836SJohn.Forte@Sun.COM 	/*
35547836SJohn.Forte@Sun.COM 	 * Check whether input buffer was large enough
35557836SJohn.Forte@Sun.COM 	 */
3556*9585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_SESSION) {
35577836SJohn.Forte@Sun.COM 		fSessionListSize = stmfIoctl.stmf_obuf_max_nentries *
35587836SJohn.Forte@Sun.COM 		    sizeof (slist_scsi_session_t);
35597836SJohn.Forte@Sun.COM 		fSessionList = realloc(fSessionList, fSessionListSize);
35607836SJohn.Forte@Sun.COM 		if (fSessionList == NULL) {
35617836SJohn.Forte@Sun.COM 			return (STMF_ERROR_NOMEM);
35627836SJohn.Forte@Sun.COM 		}
35637836SJohn.Forte@Sun.COM 		stmfIoctl.stmf_obuf_size = fSessionListSize;
35647836SJohn.Forte@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fSessionList;
35657836SJohn.Forte@Sun.COM 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
35667836SJohn.Forte@Sun.COM 		if (ioctlRet != 0) {
35677836SJohn.Forte@Sun.COM 			switch (errno) {
35687836SJohn.Forte@Sun.COM 				case EBUSY:
35697836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_BUSY;
35707836SJohn.Forte@Sun.COM 					break;
3571*9585STim.Szeto@Sun.COM 				case EPERM:
35727836SJohn.Forte@Sun.COM 				case EACCES:
35737836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_PERM;
35747836SJohn.Forte@Sun.COM 					break;
35757836SJohn.Forte@Sun.COM 				default:
35767836SJohn.Forte@Sun.COM 					syslog(LOG_DEBUG,
35777836SJohn.Forte@Sun.COM 					    "stmfGetSessionList:ioctl "
35787836SJohn.Forte@Sun.COM 					    "errno(%d)", errno);
35797836SJohn.Forte@Sun.COM 					ret = STMF_STATUS_ERROR;
35807836SJohn.Forte@Sun.COM 					break;
35817836SJohn.Forte@Sun.COM 			}
35827836SJohn.Forte@Sun.COM 			goto done;
35837836SJohn.Forte@Sun.COM 		}
35847836SJohn.Forte@Sun.COM 	}
35857836SJohn.Forte@Sun.COM 
35867836SJohn.Forte@Sun.COM 	/*
35877836SJohn.Forte@Sun.COM 	 * allocate caller's buffer with the final size
35887836SJohn.Forte@Sun.COM 	 */
35897836SJohn.Forte@Sun.COM 	*sessionList = (stmfSessionList *)calloc(1, sizeof (stmfSessionList) +
35907836SJohn.Forte@Sun.COM 	    stmfIoctl.stmf_obuf_max_nentries * sizeof (stmfSession));
35917836SJohn.Forte@Sun.COM 	if (*sessionList == NULL) {
35927836SJohn.Forte@Sun.COM 		ret = STMF_ERROR_NOMEM;
35937836SJohn.Forte@Sun.COM 		free(sessionList);
35947836SJohn.Forte@Sun.COM 		goto done;
35957836SJohn.Forte@Sun.COM 	}
35967836SJohn.Forte@Sun.COM 
35977836SJohn.Forte@Sun.COM 	(*sessionList)->cnt = stmfIoctl.stmf_obuf_max_nentries;
35987836SJohn.Forte@Sun.COM 
35997836SJohn.Forte@Sun.COM 	/*
36007836SJohn.Forte@Sun.COM 	 * copy session info to caller's buffer
36017836SJohn.Forte@Sun.COM 	 */
36027836SJohn.Forte@Sun.COM 	for (i = 0; i < (*sessionList)->cnt; i++) {
36037836SJohn.Forte@Sun.COM 		(*sessionList)->session[i].initiator.identLength =
36047836SJohn.Forte@Sun.COM 		    fSessionList->initiator[IDENT_LENGTH_BYTE];
36057836SJohn.Forte@Sun.COM 		bcopy(&(fSessionList->initiator[IDENT_LENGTH_BYTE + 1]),
36067836SJohn.Forte@Sun.COM 		    (*sessionList)->session[i].initiator.ident,
36077836SJohn.Forte@Sun.COM 		    STMF_IDENT_LENGTH);
36087836SJohn.Forte@Sun.COM 		bcopy(&(fSessionList->alias),
36097836SJohn.Forte@Sun.COM 		    &((*sessionList)->session[i].alias),
36107836SJohn.Forte@Sun.COM 		    sizeof ((*sessionList)->session[i].alias));
36117836SJohn.Forte@Sun.COM 		bcopy(&(fSessionList++->creation_time),
36127836SJohn.Forte@Sun.COM 		    &((*sessionList)->session[i].creationTime),
36137836SJohn.Forte@Sun.COM 		    sizeof (time_t));
36147836SJohn.Forte@Sun.COM 	}
36157836SJohn.Forte@Sun.COM done:
36167836SJohn.Forte@Sun.COM 	(void) close(fd);
36177836SJohn.Forte@Sun.COM 	return (ret);
36187836SJohn.Forte@Sun.COM }
36197836SJohn.Forte@Sun.COM 
36207836SJohn.Forte@Sun.COM /*
36217836SJohn.Forte@Sun.COM  * stmfGetTargetGroupList
36227836SJohn.Forte@Sun.COM  *
36237836SJohn.Forte@Sun.COM  * Purpose: Retrieves the list of target groups
36247836SJohn.Forte@Sun.COM  *
36257836SJohn.Forte@Sun.COM  * targetGroupList - pointer to a pointer to an stmfGroupList structure. On
36267836SJohn.Forte@Sun.COM  *		     success, it contains the list of target groups.
36277836SJohn.Forte@Sun.COM  */
36287836SJohn.Forte@Sun.COM int
36297836SJohn.Forte@Sun.COM stmfGetTargetGroupList(stmfGroupList **targetGroupList)
36307836SJohn.Forte@Sun.COM {
36317836SJohn.Forte@Sun.COM 	int ret;
36327836SJohn.Forte@Sun.COM 
36337836SJohn.Forte@Sun.COM 	if (targetGroupList == NULL) {
36347836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
36357836SJohn.Forte@Sun.COM 	}
36367836SJohn.Forte@Sun.COM 
3637*9585STim.Szeto@Sun.COM 	ret = groupListIoctl(targetGroupList, TARGET_GROUP);
36387836SJohn.Forte@Sun.COM 	return (ret);
36397836SJohn.Forte@Sun.COM }
36407836SJohn.Forte@Sun.COM 
36417836SJohn.Forte@Sun.COM /*
36427836SJohn.Forte@Sun.COM  * stmfGetTargetGroupMembers
36437836SJohn.Forte@Sun.COM  *
36447836SJohn.Forte@Sun.COM  * Purpose: Retrieves the group members for a target group
36457836SJohn.Forte@Sun.COM  *
36467836SJohn.Forte@Sun.COM  * groupName - name of target group for which to retrieve members.
36477836SJohn.Forte@Sun.COM  * groupProp - pointer to pointer to stmfGroupProperties structure
36487836SJohn.Forte@Sun.COM  *             on success, this contains the list of group members.
36497836SJohn.Forte@Sun.COM  */
36507836SJohn.Forte@Sun.COM int
36517836SJohn.Forte@Sun.COM stmfGetTargetGroupMembers(stmfGroupName *groupName,
36527836SJohn.Forte@Sun.COM     stmfGroupProperties **groupProp)
36537836SJohn.Forte@Sun.COM {
36547836SJohn.Forte@Sun.COM 	int ret;
36557836SJohn.Forte@Sun.COM 
36567836SJohn.Forte@Sun.COM 	if (groupName == NULL || groupProp == NULL) {
36577836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
36587836SJohn.Forte@Sun.COM 	}
36597836SJohn.Forte@Sun.COM 
3660*9585STim.Szeto@Sun.COM 	ret = groupMemberListIoctl(groupName, groupProp, TARGET_GROUP);
36617836SJohn.Forte@Sun.COM 
36627836SJohn.Forte@Sun.COM 	return (ret);
36637836SJohn.Forte@Sun.COM }
36647836SJohn.Forte@Sun.COM 
36657836SJohn.Forte@Sun.COM /*
36667836SJohn.Forte@Sun.COM  * stmfGetTargetList
36677836SJohn.Forte@Sun.COM  *
36687836SJohn.Forte@Sun.COM  * Purpose: Retrieves the list of target ports
36697836SJohn.Forte@Sun.COM  *
36707836SJohn.Forte@Sun.COM  * targetList - pointer to a pointer to an stmfDevidList structure.
36717836SJohn.Forte@Sun.COM  *		    On success, it contains the list of local ports (target).
36727836SJohn.Forte@Sun.COM  */
36737836SJohn.Forte@Sun.COM int
36747836SJohn.Forte@Sun.COM stmfGetTargetList(stmfDevidList **targetList)
36757836SJohn.Forte@Sun.COM {
36767836SJohn.Forte@Sun.COM 	int ret;
36777836SJohn.Forte@Sun.COM 	int fd;
36787836SJohn.Forte@Sun.COM 	int ioctlRet;
36797836SJohn.Forte@Sun.COM 	int i;
36807836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
36817836SJohn.Forte@Sun.COM 	/* framework target port list */
3682*9585STim.Szeto@Sun.COM 	slist_target_port_t *fTargetList, *fTargetListP = NULL;
36837836SJohn.Forte@Sun.COM 	uint32_t fTargetListSize;
36847836SJohn.Forte@Sun.COM 
36857836SJohn.Forte@Sun.COM 	if (targetList == NULL) {
36867836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
36877836SJohn.Forte@Sun.COM 	}
36887836SJohn.Forte@Sun.COM 
36897836SJohn.Forte@Sun.COM 	/* call init */
36907836SJohn.Forte@Sun.COM 	ret = initializeConfig();
36917836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
36927836SJohn.Forte@Sun.COM 		return (ret);
36937836SJohn.Forte@Sun.COM 	}
36947836SJohn.Forte@Sun.COM 
36957836SJohn.Forte@Sun.COM 	/*
36967836SJohn.Forte@Sun.COM 	 * Open control node for stmf
36977836SJohn.Forte@Sun.COM 	 */
36987836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
36997836SJohn.Forte@Sun.COM 		return (ret);
37007836SJohn.Forte@Sun.COM 
37017836SJohn.Forte@Sun.COM 	/*
37027836SJohn.Forte@Sun.COM 	 * Allocate ioctl input buffer
37037836SJohn.Forte@Sun.COM 	 */
3704*9585STim.Szeto@Sun.COM 	fTargetListSize = ALLOC_TARGET_PORT * sizeof (slist_target_port_t);
37058252SJohn.Forte@Sun.COM 	fTargetListP = fTargetList =
37068252SJohn.Forte@Sun.COM 	    (slist_target_port_t *)calloc(1, fTargetListSize);
37077836SJohn.Forte@Sun.COM 	if (fTargetList == NULL) {
3708*9585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
37097836SJohn.Forte@Sun.COM 		goto done;
37107836SJohn.Forte@Sun.COM 	}
37117836SJohn.Forte@Sun.COM 
37127836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
37137836SJohn.Forte@Sun.COM 	/*
37148252SJohn.Forte@Sun.COM 	 * Issue ioctl to retrieve target list
37157836SJohn.Forte@Sun.COM 	 */
37167836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
37177836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = fTargetListSize;
37187836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fTargetList;
37197836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_TARGET_PORT_LIST, &stmfIoctl);
37207836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
37217836SJohn.Forte@Sun.COM 		switch (errno) {
37227836SJohn.Forte@Sun.COM 			case EBUSY:
37237836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
37247836SJohn.Forte@Sun.COM 				break;
3725*9585STim.Szeto@Sun.COM 			case EPERM:
37267836SJohn.Forte@Sun.COM 			case EACCES:
37277836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
37287836SJohn.Forte@Sun.COM 				break;
37297836SJohn.Forte@Sun.COM 			default:
37307836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
37317836SJohn.Forte@Sun.COM 				    "stmfGetTargetList:ioctl errno(%d)", errno);
37327836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
37337836SJohn.Forte@Sun.COM 				break;
37347836SJohn.Forte@Sun.COM 		}
37357836SJohn.Forte@Sun.COM 		goto done;
37367836SJohn.Forte@Sun.COM 	}
37377836SJohn.Forte@Sun.COM 	/*
37387836SJohn.Forte@Sun.COM 	 * Check whether input buffer was large enough
37397836SJohn.Forte@Sun.COM 	 */
3740*9585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_TARGET_PORT) {
37417836SJohn.Forte@Sun.COM 		fTargetListSize = stmfIoctl.stmf_obuf_max_nentries *
37428116SJohn.Forte@Sun.COM 		    sizeof (slist_target_port_t);
37438252SJohn.Forte@Sun.COM 		fTargetListP = fTargetList =
37448252SJohn.Forte@Sun.COM 		    realloc(fTargetList, fTargetListSize);
37457836SJohn.Forte@Sun.COM 		if (fTargetList == NULL) {
3746*9585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NOMEM;
3747*9585STim.Szeto@Sun.COM 			goto done;
37487836SJohn.Forte@Sun.COM 		}
37497836SJohn.Forte@Sun.COM 		stmfIoctl.stmf_obuf_size = fTargetListSize;
37507836SJohn.Forte@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fTargetList;
37517836SJohn.Forte@Sun.COM 		ioctlRet = ioctl(fd, STMF_IOCTL_TARGET_PORT_LIST,
37527836SJohn.Forte@Sun.COM 		    &stmfIoctl);
37537836SJohn.Forte@Sun.COM 		if (ioctlRet != 0) {
37547836SJohn.Forte@Sun.COM 			switch (errno) {
37557836SJohn.Forte@Sun.COM 				case EBUSY:
37567836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_BUSY;
37577836SJohn.Forte@Sun.COM 					break;
3758*9585STim.Szeto@Sun.COM 				case EPERM:
37597836SJohn.Forte@Sun.COM 				case EACCES:
37607836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_PERM;
37617836SJohn.Forte@Sun.COM 					break;
37627836SJohn.Forte@Sun.COM 				default:
37637836SJohn.Forte@Sun.COM 					syslog(LOG_DEBUG,
37647836SJohn.Forte@Sun.COM 					    "stmfGetTargetList:ioctl errno(%d)",
37657836SJohn.Forte@Sun.COM 					    errno);
37667836SJohn.Forte@Sun.COM 					ret = STMF_STATUS_ERROR;
37677836SJohn.Forte@Sun.COM 					break;
37687836SJohn.Forte@Sun.COM 			}
37697836SJohn.Forte@Sun.COM 			goto done;
37707836SJohn.Forte@Sun.COM 		}
37717836SJohn.Forte@Sun.COM 	}
37727836SJohn.Forte@Sun.COM 
37737836SJohn.Forte@Sun.COM 	*targetList = (stmfDevidList *)calloc(1,
37747836SJohn.Forte@Sun.COM 	    stmfIoctl.stmf_obuf_max_nentries * sizeof (stmfDevid) +
37757836SJohn.Forte@Sun.COM 	    sizeof (stmfDevidList));
3776*9585STim.Szeto@Sun.COM 	if (*targetList == NULL) {
3777*9585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
3778*9585STim.Szeto@Sun.COM 		goto done;
3779*9585STim.Szeto@Sun.COM 	}
37807836SJohn.Forte@Sun.COM 
37817836SJohn.Forte@Sun.COM 	(*targetList)->cnt = stmfIoctl.stmf_obuf_max_nentries;
37827836SJohn.Forte@Sun.COM 	for (i = 0; i < stmfIoctl.stmf_obuf_max_nentries; i++, fTargetList++) {
37837836SJohn.Forte@Sun.COM 		(*targetList)->devid[i].identLength =
37847836SJohn.Forte@Sun.COM 		    fTargetList->target[IDENT_LENGTH_BYTE];
37857836SJohn.Forte@Sun.COM 		bcopy(&fTargetList->target[IDENT_LENGTH_BYTE + 1],
37867836SJohn.Forte@Sun.COM 		    &(*targetList)->devid[i].ident,
37877836SJohn.Forte@Sun.COM 		    fTargetList->target[IDENT_LENGTH_BYTE]);
37887836SJohn.Forte@Sun.COM 	}
37897836SJohn.Forte@Sun.COM 
37907836SJohn.Forte@Sun.COM done:
37917836SJohn.Forte@Sun.COM 	(void) close(fd);
37928252SJohn.Forte@Sun.COM 	free(fTargetListP);
37937836SJohn.Forte@Sun.COM 	return (ret);
37947836SJohn.Forte@Sun.COM }
37957836SJohn.Forte@Sun.COM 
37967836SJohn.Forte@Sun.COM /*
37977836SJohn.Forte@Sun.COM  * stmfGetTargetProperties
37987836SJohn.Forte@Sun.COM  *
37997836SJohn.Forte@Sun.COM  * Purpose:  Retrieves the properties for a logical unit
38007836SJohn.Forte@Sun.COM  *
38017836SJohn.Forte@Sun.COM  * devid - devid of the target for which to retrieve properties
38027836SJohn.Forte@Sun.COM  * targetProps - pointer to an stmfTargetProperties structure.
38037836SJohn.Forte@Sun.COM  *		On success, it contains the target properties for
38047836SJohn.Forte@Sun.COM  *		the specified devid.
38057836SJohn.Forte@Sun.COM  */
38067836SJohn.Forte@Sun.COM int
38077836SJohn.Forte@Sun.COM stmfGetTargetProperties(stmfDevid *devid, stmfTargetProperties *targetProps)
38087836SJohn.Forte@Sun.COM {
38097836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
38107836SJohn.Forte@Sun.COM 	int fd;
38117836SJohn.Forte@Sun.COM 	int ioctlRet;
38127836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
38137836SJohn.Forte@Sun.COM 	sioc_target_port_props_t targetProperties;
38147836SJohn.Forte@Sun.COM 
38157836SJohn.Forte@Sun.COM 	if (devid == NULL || targetProps == NULL) {
38167836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
38177836SJohn.Forte@Sun.COM 	}
38187836SJohn.Forte@Sun.COM 
38197836SJohn.Forte@Sun.COM 	/* call init */
38207836SJohn.Forte@Sun.COM 	ret = initializeConfig();
38217836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
38227836SJohn.Forte@Sun.COM 		return (ret);
38237836SJohn.Forte@Sun.COM 	}
38247836SJohn.Forte@Sun.COM 
38257836SJohn.Forte@Sun.COM 	/*
38267836SJohn.Forte@Sun.COM 	 * Open control node for stmf
38277836SJohn.Forte@Sun.COM 	 */
38287836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
38297836SJohn.Forte@Sun.COM 		return (ret);
38307836SJohn.Forte@Sun.COM 
38317836SJohn.Forte@Sun.COM 	targetProperties.tgt_id[IDENT_LENGTH_BYTE] = devid->identLength;
38327836SJohn.Forte@Sun.COM 	bcopy(&(devid->ident), &targetProperties.tgt_id[IDENT_LENGTH_BYTE + 1],
38337836SJohn.Forte@Sun.COM 	    devid->identLength);
38347836SJohn.Forte@Sun.COM 
38357836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
38367836SJohn.Forte@Sun.COM 	/*
38377836SJohn.Forte@Sun.COM 	 * Issue ioctl to add to the host group
38387836SJohn.Forte@Sun.COM 	 */
38397836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
38407836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (targetProperties.tgt_id);
38417836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&targetProperties.tgt_id;
38427836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&targetProperties;
38437836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = sizeof (targetProperties);
38447836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_GET_TARGET_PORT_PROPERTIES,
38457836SJohn.Forte@Sun.COM 	    &stmfIoctl);
38467836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
38477836SJohn.Forte@Sun.COM 		switch (errno) {
38487836SJohn.Forte@Sun.COM 			case EBUSY:
38497836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
38507836SJohn.Forte@Sun.COM 				break;
3851*9585STim.Szeto@Sun.COM 			case EPERM:
38527836SJohn.Forte@Sun.COM 			case EACCES:
38537836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
38547836SJohn.Forte@Sun.COM 				break;
38557836SJohn.Forte@Sun.COM 			case ENOENT:
38567836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
38577836SJohn.Forte@Sun.COM 				break;
38587836SJohn.Forte@Sun.COM 			default:
38597836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
38607836SJohn.Forte@Sun.COM 				    "stmfGetTargetProperties:ioctl errno(%d)",
38617836SJohn.Forte@Sun.COM 				    errno);
38627836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
38637836SJohn.Forte@Sun.COM 				break;
38647836SJohn.Forte@Sun.COM 		}
38657836SJohn.Forte@Sun.COM 		goto done;
38667836SJohn.Forte@Sun.COM 	}
38677836SJohn.Forte@Sun.COM 
38687836SJohn.Forte@Sun.COM 	bcopy(targetProperties.tgt_provider_name, targetProps->providerName,
38697836SJohn.Forte@Sun.COM 	    sizeof (targetProperties.tgt_provider_name));
38707836SJohn.Forte@Sun.COM 	if (targetProperties.tgt_state == STMF_STATE_ONLINE) {
38717836SJohn.Forte@Sun.COM 		targetProps->status = STMF_TARGET_PORT_ONLINE;
38727836SJohn.Forte@Sun.COM 	} else if (targetProperties.tgt_state == STMF_STATE_OFFLINE) {
38737836SJohn.Forte@Sun.COM 		targetProps->status = STMF_TARGET_PORT_OFFLINE;
38747836SJohn.Forte@Sun.COM 	} else if (targetProperties.tgt_state == STMF_STATE_ONLINING) {
38757836SJohn.Forte@Sun.COM 		targetProps->status = STMF_TARGET_PORT_ONLINING;
38767836SJohn.Forte@Sun.COM 	} else if (targetProperties.tgt_state == STMF_STATE_OFFLINING) {
38777836SJohn.Forte@Sun.COM 		targetProps->status = STMF_TARGET_PORT_OFFLINING;
38787836SJohn.Forte@Sun.COM 	}
38797836SJohn.Forte@Sun.COM 	bcopy(targetProperties.tgt_alias, targetProps->alias,
38807836SJohn.Forte@Sun.COM 	    sizeof (targetProps->alias));
38817836SJohn.Forte@Sun.COM done:
38827836SJohn.Forte@Sun.COM 	(void) close(fd);
38837836SJohn.Forte@Sun.COM 	return (ret);
38847836SJohn.Forte@Sun.COM }
38857836SJohn.Forte@Sun.COM 
38867836SJohn.Forte@Sun.COM /*
38877836SJohn.Forte@Sun.COM  * stmfGetLogicalUnitList
38887836SJohn.Forte@Sun.COM  *
38897836SJohn.Forte@Sun.COM  * Purpose: Retrieves list of logical unit Object IDs
38907836SJohn.Forte@Sun.COM  *
38917836SJohn.Forte@Sun.COM  * luList - pointer to a pointer to a stmfGuidList structure. On success,
38927836SJohn.Forte@Sun.COM  *          it contains the list of logical unit guids.
38937836SJohn.Forte@Sun.COM  *
38947836SJohn.Forte@Sun.COM  */
38957836SJohn.Forte@Sun.COM int
38967836SJohn.Forte@Sun.COM stmfGetLogicalUnitList(stmfGuidList **luList)
38977836SJohn.Forte@Sun.COM {
38987836SJohn.Forte@Sun.COM 	int ret;
38997836SJohn.Forte@Sun.COM 	int fd;
39007836SJohn.Forte@Sun.COM 	int ioctlRet;
39017836SJohn.Forte@Sun.COM 	int cmd = STMF_IOCTL_LU_LIST;
3902*9585STim.Szeto@Sun.COM 	int i;
39037836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
39047836SJohn.Forte@Sun.COM 	slist_lu_t *fLuList;
39057836SJohn.Forte@Sun.COM 	uint32_t fLuListSize;
3906*9585STim.Szeto@Sun.COM 	uint32_t listCnt;
39077836SJohn.Forte@Sun.COM 
39087836SJohn.Forte@Sun.COM 	if (luList == NULL) {
39097836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
39107836SJohn.Forte@Sun.COM 	}
39117836SJohn.Forte@Sun.COM 
39127836SJohn.Forte@Sun.COM 	/* call init */
39137836SJohn.Forte@Sun.COM 	ret = initializeConfig();
39147836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
39157836SJohn.Forte@Sun.COM 		return (ret);
39167836SJohn.Forte@Sun.COM 	}
39177836SJohn.Forte@Sun.COM 
39187836SJohn.Forte@Sun.COM 	/*
39197836SJohn.Forte@Sun.COM 	 * Open control node for stmf
39207836SJohn.Forte@Sun.COM 	 */
39217836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
39227836SJohn.Forte@Sun.COM 		return (ret);
39237836SJohn.Forte@Sun.COM 
39247836SJohn.Forte@Sun.COM 	/*
39257836SJohn.Forte@Sun.COM 	 * Allocate ioctl input buffer
39267836SJohn.Forte@Sun.COM 	 */
3927*9585STim.Szeto@Sun.COM 	fLuListSize = ALLOC_LU;
39287836SJohn.Forte@Sun.COM 	fLuListSize = fLuListSize * (sizeof (slist_lu_t));
39297836SJohn.Forte@Sun.COM 	fLuList = (slist_lu_t *)calloc(1, fLuListSize);
39307836SJohn.Forte@Sun.COM 	if (fLuList == NULL) {
3931*9585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
3932*9585STim.Szeto@Sun.COM 		goto done;
39337836SJohn.Forte@Sun.COM 	}
39347836SJohn.Forte@Sun.COM 
39357836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
39367836SJohn.Forte@Sun.COM 	/*
39377836SJohn.Forte@Sun.COM 	 * Issue ioctl to get the LU list
39387836SJohn.Forte@Sun.COM 	 */
39397836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
39407836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = fLuListSize;
39417836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fLuList;
39427836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
39437836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
39447836SJohn.Forte@Sun.COM 		switch (errno) {
39457836SJohn.Forte@Sun.COM 			case EBUSY:
39467836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
39477836SJohn.Forte@Sun.COM 				break;
3948*9585STim.Szeto@Sun.COM 			case EPERM:
39497836SJohn.Forte@Sun.COM 			case EACCES:
39507836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
39517836SJohn.Forte@Sun.COM 				break;
39527836SJohn.Forte@Sun.COM 			default:
39537836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
39547836SJohn.Forte@Sun.COM 				    "stmfGetLogicalUnitList:ioctl errno(%d)",
39557836SJohn.Forte@Sun.COM 				    errno);
39567836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
39577836SJohn.Forte@Sun.COM 				break;
39587836SJohn.Forte@Sun.COM 		}
39597836SJohn.Forte@Sun.COM 		goto done;
39607836SJohn.Forte@Sun.COM 	}
39617836SJohn.Forte@Sun.COM 	/*
39627836SJohn.Forte@Sun.COM 	 * Check whether input buffer was large enough
39637836SJohn.Forte@Sun.COM 	 */
3964*9585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_LU) {
39657836SJohn.Forte@Sun.COM 		fLuListSize = stmfIoctl.stmf_obuf_max_nentries *
39667836SJohn.Forte@Sun.COM 		    sizeof (slist_lu_t);
3967*9585STim.Szeto@Sun.COM 		free(fLuList);
3968*9585STim.Szeto@Sun.COM 		fLuList = (slist_lu_t *)calloc(1, fLuListSize);
39697836SJohn.Forte@Sun.COM 		if (fLuList == NULL) {
3970*9585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NOMEM;
3971*9585STim.Szeto@Sun.COM 			goto done;
39727836SJohn.Forte@Sun.COM 		}
39737836SJohn.Forte@Sun.COM 		stmfIoctl.stmf_obuf_size = fLuListSize;
39747836SJohn.Forte@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fLuList;
39757836SJohn.Forte@Sun.COM 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
39767836SJohn.Forte@Sun.COM 		if (ioctlRet != 0) {
39777836SJohn.Forte@Sun.COM 			switch (errno) {
39787836SJohn.Forte@Sun.COM 				case EBUSY:
39797836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_BUSY;
39807836SJohn.Forte@Sun.COM 					break;
3981*9585STim.Szeto@Sun.COM 				case EPERM:
39827836SJohn.Forte@Sun.COM 				case EACCES:
39837836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_PERM;
39847836SJohn.Forte@Sun.COM 					break;
39857836SJohn.Forte@Sun.COM 				default:
39867836SJohn.Forte@Sun.COM 					syslog(LOG_DEBUG,
39877836SJohn.Forte@Sun.COM 					    "stmfGetLogicalUnitList:"
39887836SJohn.Forte@Sun.COM 					    "ioctl errno(%d)", errno);
39897836SJohn.Forte@Sun.COM 					ret = STMF_STATUS_ERROR;
39907836SJohn.Forte@Sun.COM 					break;
39917836SJohn.Forte@Sun.COM 			}
39927836SJohn.Forte@Sun.COM 			goto done;
39937836SJohn.Forte@Sun.COM 		}
39947836SJohn.Forte@Sun.COM 	}
39957836SJohn.Forte@Sun.COM 
39967836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
39977836SJohn.Forte@Sun.COM 		goto done;
39987836SJohn.Forte@Sun.COM 	}
39997836SJohn.Forte@Sun.COM 
4000*9585STim.Szeto@Sun.COM 	listCnt = stmfIoctl.stmf_obuf_nentries;
40017836SJohn.Forte@Sun.COM 
40027836SJohn.Forte@Sun.COM 	/*
40037836SJohn.Forte@Sun.COM 	 * allocate caller's buffer with the final size
40047836SJohn.Forte@Sun.COM 	 */
40057836SJohn.Forte@Sun.COM 	*luList = (stmfGuidList *)calloc(1, sizeof (stmfGuidList) +
4006*9585STim.Szeto@Sun.COM 	    listCnt * sizeof (stmfGuid));
40077836SJohn.Forte@Sun.COM 	if (*luList == NULL) {
40087836SJohn.Forte@Sun.COM 		ret = STMF_ERROR_NOMEM;
40097836SJohn.Forte@Sun.COM 		goto done;
40107836SJohn.Forte@Sun.COM 	}
40117836SJohn.Forte@Sun.COM 
4012*9585STim.Szeto@Sun.COM 	(*luList)->cnt = listCnt;
4013*9585STim.Szeto@Sun.COM 
4014*9585STim.Szeto@Sun.COM 	/* copy to caller's buffer */
4015*9585STim.Szeto@Sun.COM 	for (i = 0; i < listCnt; i++) {
4016*9585STim.Szeto@Sun.COM 		bcopy(&fLuList[i].lu_guid, (*luList)->guid[i].guid,
4017*9585STim.Szeto@Sun.COM 		    sizeof (stmfGuid));
4018*9585STim.Szeto@Sun.COM 	}
4019*9585STim.Szeto@Sun.COM 
40207836SJohn.Forte@Sun.COM 	/*
4021*9585STim.Szeto@Sun.COM 	 * sort the list. This gives a consistent view across gets
40227836SJohn.Forte@Sun.COM 	 */
4023*9585STim.Szeto@Sun.COM 	qsort((void *)&((*luList)->guid[0]), (*luList)->cnt,
4024*9585STim.Szeto@Sun.COM 	    sizeof (stmfGuid), guidCompare);
40257836SJohn.Forte@Sun.COM 
40267836SJohn.Forte@Sun.COM done:
40277836SJohn.Forte@Sun.COM 	(void) close(fd);
40287836SJohn.Forte@Sun.COM 	/*
40297836SJohn.Forte@Sun.COM 	 * free internal buffers
40307836SJohn.Forte@Sun.COM 	 */
40317836SJohn.Forte@Sun.COM 	free(fLuList);
40327836SJohn.Forte@Sun.COM 	return (ret);
40337836SJohn.Forte@Sun.COM }
40347836SJohn.Forte@Sun.COM 
40357836SJohn.Forte@Sun.COM /*
40367836SJohn.Forte@Sun.COM  * stmfGetLogicalUnitProperties
40377836SJohn.Forte@Sun.COM  *
40387836SJohn.Forte@Sun.COM  * Purpose:  Retrieves the properties for a logical unit
40397836SJohn.Forte@Sun.COM  *
40407836SJohn.Forte@Sun.COM  * lu - guid of the logical unit for which to retrieve properties
40417836SJohn.Forte@Sun.COM  * stmfLuProps - pointer to an stmfLogicalUnitProperties structure. On success,
40427836SJohn.Forte@Sun.COM  *               it contains the logical unit properties for the specified guid.
40437836SJohn.Forte@Sun.COM  */
40447836SJohn.Forte@Sun.COM int
40457836SJohn.Forte@Sun.COM stmfGetLogicalUnitProperties(stmfGuid *lu, stmfLogicalUnitProperties *luProps)
40467836SJohn.Forte@Sun.COM {
40477836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
40487836SJohn.Forte@Sun.COM 	int stmfRet;
40497836SJohn.Forte@Sun.COM 	int fd;
40507836SJohn.Forte@Sun.COM 	int ioctlRet;
40517836SJohn.Forte@Sun.COM 	int cmd = STMF_IOCTL_GET_LU_PROPERTIES;
40527836SJohn.Forte@Sun.COM 	stmfViewEntryList *viewEntryList = NULL;
40537836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
40547836SJohn.Forte@Sun.COM 	sioc_lu_props_t fLuProps;
40557836SJohn.Forte@Sun.COM 
4056*9585STim.Szeto@Sun.COM 	if (lu == NULL || luProps == NULL) {
4057*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
40587836SJohn.Forte@Sun.COM 	}
40597836SJohn.Forte@Sun.COM 
40607836SJohn.Forte@Sun.COM 	bzero(luProps, sizeof (stmfLogicalUnitProperties));
40617836SJohn.Forte@Sun.COM 
40627836SJohn.Forte@Sun.COM 	/* call init */
40637836SJohn.Forte@Sun.COM 	ret = initializeConfig();
40647836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
40657836SJohn.Forte@Sun.COM 		return (ret);
40667836SJohn.Forte@Sun.COM 	}
40677836SJohn.Forte@Sun.COM 
40687836SJohn.Forte@Sun.COM 	/*
40697836SJohn.Forte@Sun.COM 	 * Open control node for stmf
40707836SJohn.Forte@Sun.COM 	 */
40717836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
40727836SJohn.Forte@Sun.COM 		return (ret);
40737836SJohn.Forte@Sun.COM 
40747836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
40757836SJohn.Forte@Sun.COM 	/*
40767836SJohn.Forte@Sun.COM 	 * Issue ioctl to add to the host group
40777836SJohn.Forte@Sun.COM 	 */
40787836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
40797836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (stmfGuid);
40807836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)lu;
40817836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&fLuProps;
40827836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = sizeof (fLuProps);
40837836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
40847836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
40857836SJohn.Forte@Sun.COM 		switch (errno) {
40867836SJohn.Forte@Sun.COM 			case EBUSY:
40877836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
40887836SJohn.Forte@Sun.COM 				break;
4089*9585STim.Szeto@Sun.COM 			case EPERM:
40907836SJohn.Forte@Sun.COM 			case EACCES:
40917836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
40927836SJohn.Forte@Sun.COM 				break;
40937836SJohn.Forte@Sun.COM 			case ENOENT:
40947836SJohn.Forte@Sun.COM 				stmfRet = stmfGetViewEntryList(lu,
40957836SJohn.Forte@Sun.COM 				    &viewEntryList);
40967836SJohn.Forte@Sun.COM 				if (stmfRet == STMF_STATUS_SUCCESS) {
40977836SJohn.Forte@Sun.COM 					luProps->status =
40987836SJohn.Forte@Sun.COM 					    STMF_LOGICAL_UNIT_UNREGISTERED;
40997836SJohn.Forte@Sun.COM 					if (viewEntryList->cnt > 0) {
41007836SJohn.Forte@Sun.COM 						ret = STMF_STATUS_SUCCESS;
41017836SJohn.Forte@Sun.COM 					} else {
41027836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_NOT_FOUND;
41037836SJohn.Forte@Sun.COM 					}
41047836SJohn.Forte@Sun.COM 				} else {
41057836SJohn.Forte@Sun.COM 					ret = STMF_ERROR_NOT_FOUND;
41067836SJohn.Forte@Sun.COM 				}
41077836SJohn.Forte@Sun.COM 				stmfFreeMemory(viewEntryList);
41087836SJohn.Forte@Sun.COM 				break;
41097836SJohn.Forte@Sun.COM 			default:
41107836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
41117836SJohn.Forte@Sun.COM 				    "stmfGetLogicalUnit:ioctl errno(%d)",
41127836SJohn.Forte@Sun.COM 				    errno);
41137836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
41147836SJohn.Forte@Sun.COM 				break;
41157836SJohn.Forte@Sun.COM 		}
41167836SJohn.Forte@Sun.COM 		goto done;
41177836SJohn.Forte@Sun.COM 	}
41187836SJohn.Forte@Sun.COM 
41197836SJohn.Forte@Sun.COM 	bcopy(fLuProps.lu_provider_name, luProps->providerName,
41207836SJohn.Forte@Sun.COM 	    sizeof (fLuProps.lu_provider_name));
41217836SJohn.Forte@Sun.COM 	if (fLuProps.lu_state == STMF_STATE_ONLINE) {
41227836SJohn.Forte@Sun.COM 		luProps->status = STMF_LOGICAL_UNIT_ONLINE;
41237836SJohn.Forte@Sun.COM 	} else if (fLuProps.lu_state == STMF_STATE_OFFLINE) {
41247836SJohn.Forte@Sun.COM 		luProps->status = STMF_LOGICAL_UNIT_OFFLINE;
41257836SJohn.Forte@Sun.COM 	} else if (fLuProps.lu_state == STMF_STATE_ONLINING) {
41267836SJohn.Forte@Sun.COM 		luProps->status = STMF_LOGICAL_UNIT_ONLINING;
41277836SJohn.Forte@Sun.COM 	} else if (fLuProps.lu_state == STMF_STATE_OFFLINING) {
41287836SJohn.Forte@Sun.COM 		luProps->status = STMF_LOGICAL_UNIT_OFFLINING;
41297836SJohn.Forte@Sun.COM 	}
41307836SJohn.Forte@Sun.COM 	bcopy(fLuProps.lu_alias, luProps->alias, sizeof (luProps->alias));
41317836SJohn.Forte@Sun.COM done:
41327836SJohn.Forte@Sun.COM 	(void) close(fd);
41337836SJohn.Forte@Sun.COM 	return (ret);
41347836SJohn.Forte@Sun.COM }
41357836SJohn.Forte@Sun.COM 
41367836SJohn.Forte@Sun.COM /*
41377836SJohn.Forte@Sun.COM  * stmfGetState
41387836SJohn.Forte@Sun.COM  *
41397836SJohn.Forte@Sun.COM  * Purpose: retrieve the current state of the stmf module
41407836SJohn.Forte@Sun.COM  *
41417836SJohn.Forte@Sun.COM  * state - pointer to stmfState structure allocated by the caller
41427836SJohn.Forte@Sun.COM  *         On success, contains the state of stmf
41437836SJohn.Forte@Sun.COM  */
41447836SJohn.Forte@Sun.COM int
41457836SJohn.Forte@Sun.COM stmfGetState(stmfState *state)
41467836SJohn.Forte@Sun.COM {
41477836SJohn.Forte@Sun.COM 	int ret;
41487836SJohn.Forte@Sun.COM 	stmf_state_desc_t iState;
41497836SJohn.Forte@Sun.COM 
41507836SJohn.Forte@Sun.COM 	if (state == NULL) {
41517836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
41527836SJohn.Forte@Sun.COM 	}
41537836SJohn.Forte@Sun.COM 
41547836SJohn.Forte@Sun.COM 	ret = getStmfState(&iState);
41557836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
41567836SJohn.Forte@Sun.COM 		return (ret);
41577836SJohn.Forte@Sun.COM 	}
41587836SJohn.Forte@Sun.COM 	switch (iState.state) {
41597836SJohn.Forte@Sun.COM 		case STMF_STATE_ONLINE:
41607836SJohn.Forte@Sun.COM 			state->operationalState =
41617836SJohn.Forte@Sun.COM 			    STMF_SERVICE_STATE_ONLINE;
41627836SJohn.Forte@Sun.COM 			break;
41637836SJohn.Forte@Sun.COM 		case STMF_STATE_OFFLINE:
41647836SJohn.Forte@Sun.COM 			state->operationalState =
41657836SJohn.Forte@Sun.COM 			    STMF_SERVICE_STATE_OFFLINE;
41667836SJohn.Forte@Sun.COM 			break;
41677836SJohn.Forte@Sun.COM 		case STMF_STATE_ONLINING:
41687836SJohn.Forte@Sun.COM 			state->operationalState =
41697836SJohn.Forte@Sun.COM 			    STMF_SERVICE_STATE_ONLINING;
41707836SJohn.Forte@Sun.COM 			break;
41717836SJohn.Forte@Sun.COM 		case STMF_STATE_OFFLINING:
41727836SJohn.Forte@Sun.COM 			state->operationalState =
41737836SJohn.Forte@Sun.COM 			    STMF_SERVICE_STATE_OFFLINING;
41747836SJohn.Forte@Sun.COM 			break;
41757836SJohn.Forte@Sun.COM 		default:
41767836SJohn.Forte@Sun.COM 			state->operationalState =
41777836SJohn.Forte@Sun.COM 			    STMF_SERVICE_STATE_UNKNOWN;
41787836SJohn.Forte@Sun.COM 			break;
41797836SJohn.Forte@Sun.COM 	}
41807836SJohn.Forte@Sun.COM 	switch (iState.config_state) {
41817836SJohn.Forte@Sun.COM 		case STMF_CONFIG_NONE:
41827836SJohn.Forte@Sun.COM 			state->configState = STMF_CONFIG_STATE_NONE;
41837836SJohn.Forte@Sun.COM 			break;
41847836SJohn.Forte@Sun.COM 		case STMF_CONFIG_INIT:
41857836SJohn.Forte@Sun.COM 			state->configState = STMF_CONFIG_STATE_INIT;
41867836SJohn.Forte@Sun.COM 			break;
41877836SJohn.Forte@Sun.COM 		case STMF_CONFIG_INIT_DONE:
41887836SJohn.Forte@Sun.COM 			state->configState =
41897836SJohn.Forte@Sun.COM 			    STMF_CONFIG_STATE_INIT_DONE;
41907836SJohn.Forte@Sun.COM 			break;
41917836SJohn.Forte@Sun.COM 		default:
41927836SJohn.Forte@Sun.COM 			state->configState =
41937836SJohn.Forte@Sun.COM 			    STMF_CONFIG_STATE_UNKNOWN;
41947836SJohn.Forte@Sun.COM 			break;
41957836SJohn.Forte@Sun.COM 	}
41967836SJohn.Forte@Sun.COM 	return (STMF_STATUS_SUCCESS);
41977836SJohn.Forte@Sun.COM }
41987836SJohn.Forte@Sun.COM 
41997836SJohn.Forte@Sun.COM /*
42007836SJohn.Forte@Sun.COM  * stmfGetViewEntryList
42017836SJohn.Forte@Sun.COM  *
42027836SJohn.Forte@Sun.COM  * Purpose: Retrieves the list of view entries for the specified
42037836SJohn.Forte@Sun.COM  *          logical unit.
42047836SJohn.Forte@Sun.COM  *
42057836SJohn.Forte@Sun.COM  * lu - the guid of the logical unit for which to retrieve the view entry list
42067836SJohn.Forte@Sun.COM  * viewEntryList - a pointer to a pointer to a stmfViewEntryList structure. On
42077836SJohn.Forte@Sun.COM  *                 success, contains the list of view entries.
42087836SJohn.Forte@Sun.COM  */
42097836SJohn.Forte@Sun.COM int
42107836SJohn.Forte@Sun.COM stmfGetViewEntryList(stmfGuid *lu, stmfViewEntryList **viewEntryList)
42117836SJohn.Forte@Sun.COM {
42127836SJohn.Forte@Sun.COM 	int ret;
4213*9585STim.Szeto@Sun.COM 	int fd;
4214*9585STim.Szeto@Sun.COM 	int ioctlRet;
4215*9585STim.Szeto@Sun.COM 	int cmd = STMF_IOCTL_LU_VE_LIST;
4216*9585STim.Szeto@Sun.COM 	int i;
4217*9585STim.Szeto@Sun.COM 	stmf_iocdata_t stmfIoctl;
4218*9585STim.Szeto@Sun.COM 	stmf_view_op_entry_t *fVeList;
4219*9585STim.Szeto@Sun.COM 	uint32_t fVeListSize;
4220*9585STim.Szeto@Sun.COM 	uint32_t listCnt;
42217836SJohn.Forte@Sun.COM 
42227836SJohn.Forte@Sun.COM 	if (lu == NULL || viewEntryList == NULL) {
42237836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
42247836SJohn.Forte@Sun.COM 	}
42257836SJohn.Forte@Sun.COM 
4226*9585STim.Szeto@Sun.COM 	/* call init */
4227*9585STim.Szeto@Sun.COM 	ret = initializeConfig();
4228*9585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
4229*9585STim.Szeto@Sun.COM 		return (ret);
4230*9585STim.Szeto@Sun.COM 	}
4231*9585STim.Szeto@Sun.COM 
4232*9585STim.Szeto@Sun.COM 	/*
4233*9585STim.Szeto@Sun.COM 	 * Open control node for stmf
4234*9585STim.Szeto@Sun.COM 	 */
4235*9585STim.Szeto@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
4236*9585STim.Szeto@Sun.COM 		return (ret);
4237*9585STim.Szeto@Sun.COM 
4238*9585STim.Szeto@Sun.COM 	/*
4239*9585STim.Szeto@Sun.COM 	 * Allocate ioctl input buffer
4240*9585STim.Szeto@Sun.COM 	 */
4241*9585STim.Szeto@Sun.COM 	fVeListSize = ALLOC_VE;
4242*9585STim.Szeto@Sun.COM 	fVeListSize = fVeListSize * (sizeof (stmf_view_op_entry_t));
4243*9585STim.Szeto@Sun.COM 	fVeList = (stmf_view_op_entry_t *)calloc(1, fVeListSize);
4244*9585STim.Szeto@Sun.COM 	if (fVeList == NULL) {
4245*9585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
4246*9585STim.Szeto@Sun.COM 		goto done;
4247*9585STim.Szeto@Sun.COM 	}
4248*9585STim.Szeto@Sun.COM 
4249*9585STim.Szeto@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
4250*9585STim.Szeto@Sun.COM 	/*
4251*9585STim.Szeto@Sun.COM 	 * Issue ioctl to get the LU list
4252*9585STim.Szeto@Sun.COM 	 */
4253*9585STim.Szeto@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
4254*9585STim.Szeto@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)lu;
4255*9585STim.Szeto@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (stmfGuid);
4256*9585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf_size = fVeListSize;
4257*9585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fVeList;
4258*9585STim.Szeto@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
4259*9585STim.Szeto@Sun.COM 	if (ioctlRet != 0) {
4260*9585STim.Szeto@Sun.COM 		switch (errno) {
4261*9585STim.Szeto@Sun.COM 			case EBUSY:
4262*9585STim.Szeto@Sun.COM 				ret = STMF_ERROR_BUSY;
4263*9585STim.Szeto@Sun.COM 				break;
4264*9585STim.Szeto@Sun.COM 			case EPERM:
4265*9585STim.Szeto@Sun.COM 			case EACCES:
4266*9585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
4267*9585STim.Szeto@Sun.COM 				break;
4268*9585STim.Szeto@Sun.COM 			default:
4269*9585STim.Szeto@Sun.COM 				syslog(LOG_DEBUG,
4270*9585STim.Szeto@Sun.COM 				    "stmfGetViewEntryList:ioctl errno(%d)",
4271*9585STim.Szeto@Sun.COM 				    errno);
4272*9585STim.Szeto@Sun.COM 				ret = STMF_STATUS_ERROR;
4273*9585STim.Szeto@Sun.COM 				break;
4274*9585STim.Szeto@Sun.COM 		}
4275*9585STim.Szeto@Sun.COM 		goto done;
4276*9585STim.Szeto@Sun.COM 	}
4277*9585STim.Szeto@Sun.COM 	/*
4278*9585STim.Szeto@Sun.COM 	 * Check whether input buffer was large enough
4279*9585STim.Szeto@Sun.COM 	 */
4280*9585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_VE) {
4281*9585STim.Szeto@Sun.COM 		bzero(&stmfIoctl, sizeof (stmfIoctl));
4282*9585STim.Szeto@Sun.COM 		fVeListSize = stmfIoctl.stmf_obuf_max_nentries *
4283*9585STim.Szeto@Sun.COM 		    sizeof (stmf_view_op_entry_t);
4284*9585STim.Szeto@Sun.COM 		free(fVeList);
4285*9585STim.Szeto@Sun.COM 		fVeList = (stmf_view_op_entry_t *)calloc(1, fVeListSize);
4286*9585STim.Szeto@Sun.COM 		if (fVeList == NULL) {
4287*9585STim.Szeto@Sun.COM 			return (STMF_ERROR_NOMEM);
4288*9585STim.Szeto@Sun.COM 		}
4289*9585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf_size = fVeListSize;
4290*9585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fVeList;
4291*9585STim.Szeto@Sun.COM 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
4292*9585STim.Szeto@Sun.COM 		if (ioctlRet != 0) {
4293*9585STim.Szeto@Sun.COM 			switch (errno) {
4294*9585STim.Szeto@Sun.COM 				case EBUSY:
4295*9585STim.Szeto@Sun.COM 					ret = STMF_ERROR_BUSY;
4296*9585STim.Szeto@Sun.COM 					break;
4297*9585STim.Szeto@Sun.COM 				case EPERM:
4298*9585STim.Szeto@Sun.COM 				case EACCES:
4299*9585STim.Szeto@Sun.COM 					ret = STMF_ERROR_PERM;
4300*9585STim.Szeto@Sun.COM 					break;
4301*9585STim.Szeto@Sun.COM 				default:
4302*9585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
4303*9585STim.Szeto@Sun.COM 					    "stmfGetLogicalUnitList:"
4304*9585STim.Szeto@Sun.COM 					    "ioctl errno(%d)", errno);
4305*9585STim.Szeto@Sun.COM 					ret = STMF_STATUS_ERROR;
4306*9585STim.Szeto@Sun.COM 					break;
4307*9585STim.Szeto@Sun.COM 			}
4308*9585STim.Szeto@Sun.COM 			goto done;
4309*9585STim.Szeto@Sun.COM 		}
4310*9585STim.Szeto@Sun.COM 	}
4311*9585STim.Szeto@Sun.COM 
4312*9585STim.Szeto@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
4313*9585STim.Szeto@Sun.COM 		goto done;
4314*9585STim.Szeto@Sun.COM 	}
4315*9585STim.Szeto@Sun.COM 
4316*9585STim.Szeto@Sun.COM 	if (stmfIoctl.stmf_obuf_nentries == 0) {
4317*9585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOT_FOUND;
4318*9585STim.Szeto@Sun.COM 		goto done;
4319*9585STim.Szeto@Sun.COM 	}
4320*9585STim.Szeto@Sun.COM 
4321*9585STim.Szeto@Sun.COM 	listCnt = stmfIoctl.stmf_obuf_nentries;
4322*9585STim.Szeto@Sun.COM 
4323*9585STim.Szeto@Sun.COM 	/*
4324*9585STim.Szeto@Sun.COM 	 * allocate caller's buffer with the final size
4325*9585STim.Szeto@Sun.COM 	 */
4326*9585STim.Szeto@Sun.COM 	*viewEntryList = (stmfViewEntryList *)calloc(1,
4327*9585STim.Szeto@Sun.COM 	    sizeof (stmfViewEntryList) + listCnt * sizeof (stmfViewEntry));
4328*9585STim.Szeto@Sun.COM 	if (*viewEntryList == NULL) {
4329*9585STim.Szeto@Sun.COM 		ret = STMF_ERROR_NOMEM;
4330*9585STim.Szeto@Sun.COM 		goto done;
4331*9585STim.Szeto@Sun.COM 	}
4332*9585STim.Szeto@Sun.COM 
4333*9585STim.Szeto@Sun.COM 	(*viewEntryList)->cnt = listCnt;
4334*9585STim.Szeto@Sun.COM 
4335*9585STim.Szeto@Sun.COM 	/* copy to caller's buffer */
4336*9585STim.Szeto@Sun.COM 	for (i = 0; i < listCnt; i++) {
4337*9585STim.Szeto@Sun.COM 		(*viewEntryList)->ve[i].veIndexValid = B_TRUE;
4338*9585STim.Szeto@Sun.COM 		(*viewEntryList)->ve[i].veIndex = fVeList[i].ve_ndx;
4339*9585STim.Szeto@Sun.COM 		if (fVeList[i].ve_all_hosts == 1) {
4340*9585STim.Szeto@Sun.COM 			(*viewEntryList)->ve[i].allHosts = B_TRUE;
4341*9585STim.Szeto@Sun.COM 		} else {
4342*9585STim.Szeto@Sun.COM 			bcopy(fVeList[i].ve_host_group.name,
4343*9585STim.Szeto@Sun.COM 			    (*viewEntryList)->ve[i].hostGroup,
4344*9585STim.Szeto@Sun.COM 			    fVeList[i].ve_host_group.name_size);
4345*9585STim.Szeto@Sun.COM 		}
4346*9585STim.Szeto@Sun.COM 		if (fVeList[i].ve_all_targets == 1) {
4347*9585STim.Szeto@Sun.COM 			(*viewEntryList)->ve[i].allTargets = B_TRUE;
4348*9585STim.Szeto@Sun.COM 		} else {
4349*9585STim.Szeto@Sun.COM 			bcopy(fVeList[i].ve_target_group.name,
4350*9585STim.Szeto@Sun.COM 			    (*viewEntryList)->ve[i].targetGroup,
4351*9585STim.Szeto@Sun.COM 			    fVeList[i].ve_target_group.name_size);
4352*9585STim.Szeto@Sun.COM 		}
4353*9585STim.Szeto@Sun.COM 		bcopy(fVeList[i].ve_lu_nbr, (*viewEntryList)->ve[i].luNbr,
4354*9585STim.Szeto@Sun.COM 		    sizeof ((*viewEntryList)->ve[i].luNbr));
4355*9585STim.Szeto@Sun.COM 		(*viewEntryList)->ve[i].luNbrValid = B_TRUE;
4356*9585STim.Szeto@Sun.COM 	}
4357*9585STim.Szeto@Sun.COM 
4358*9585STim.Szeto@Sun.COM 	/*
4359*9585STim.Szeto@Sun.COM 	 * sort the list. This gives a consistent view across gets
4360*9585STim.Szeto@Sun.COM 	 */
4361*9585STim.Szeto@Sun.COM 	qsort((void *)&((*viewEntryList)->ve[0]), (*viewEntryList)->cnt,
4362*9585STim.Szeto@Sun.COM 	    sizeof (stmfViewEntry), viewEntryCompare);
4363*9585STim.Szeto@Sun.COM 
4364*9585STim.Szeto@Sun.COM done:
4365*9585STim.Szeto@Sun.COM 	(void) close(fd);
4366*9585STim.Szeto@Sun.COM 	/*
4367*9585STim.Szeto@Sun.COM 	 * free internal buffers
4368*9585STim.Szeto@Sun.COM 	 */
4369*9585STim.Szeto@Sun.COM 	free(fVeList);
43707836SJohn.Forte@Sun.COM 	return (ret);
43717836SJohn.Forte@Sun.COM }
43727836SJohn.Forte@Sun.COM 
4373*9585STim.Szeto@Sun.COM 
43747836SJohn.Forte@Sun.COM /*
43757836SJohn.Forte@Sun.COM  * loadHostGroups
43767836SJohn.Forte@Sun.COM  *
43777836SJohn.Forte@Sun.COM  * Purpose - issues the ioctl to load the host groups into stmf
43787836SJohn.Forte@Sun.COM  *
43797836SJohn.Forte@Sun.COM  * fd - file descriptor for the control node of stmf.
43807836SJohn.Forte@Sun.COM  * groupList - populated host group list
43817836SJohn.Forte@Sun.COM  */
43827836SJohn.Forte@Sun.COM static int
43837836SJohn.Forte@Sun.COM loadHostGroups(int fd, stmfGroupList *groupList)
43847836SJohn.Forte@Sun.COM {
43857836SJohn.Forte@Sun.COM 	int i, j;
43867836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
43877836SJohn.Forte@Sun.COM 	stmfGroupProperties *groupProps = NULL;
43887836SJohn.Forte@Sun.COM 
43897836SJohn.Forte@Sun.COM 	for (i = 0; i < groupList->cnt; i++) {
43907836SJohn.Forte@Sun.COM 		if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_HOST_GROUP,
43917836SJohn.Forte@Sun.COM 		    &(groupList->name[i]))) != STMF_STATUS_SUCCESS) {
43927836SJohn.Forte@Sun.COM 			goto out;
43937836SJohn.Forte@Sun.COM 		}
4394*9585STim.Szeto@Sun.COM 		ret = iLoadGroupMembersFromPs(&(groupList->name[i]),
4395*9585STim.Szeto@Sun.COM 		    &groupProps, HOST_GROUP);
43967836SJohn.Forte@Sun.COM 		for (j = 0; j < groupProps->cnt; j++) {
43977836SJohn.Forte@Sun.COM 			if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_HG_ENTRY,
43987836SJohn.Forte@Sun.COM 			    &(groupList->name[i]), &(groupProps->name[j])))
43997836SJohn.Forte@Sun.COM 			    != STMF_STATUS_SUCCESS) {
44007836SJohn.Forte@Sun.COM 				goto out;
44017836SJohn.Forte@Sun.COM 			}
44027836SJohn.Forte@Sun.COM 		}
44037836SJohn.Forte@Sun.COM 	}
44047836SJohn.Forte@Sun.COM 
44057836SJohn.Forte@Sun.COM 
44067836SJohn.Forte@Sun.COM out:
44077836SJohn.Forte@Sun.COM 	stmfFreeMemory(groupProps);
44087836SJohn.Forte@Sun.COM 	return (ret);
44097836SJohn.Forte@Sun.COM }
44107836SJohn.Forte@Sun.COM 
44117836SJohn.Forte@Sun.COM /*
44127836SJohn.Forte@Sun.COM  * loadTargetGroups
44137836SJohn.Forte@Sun.COM  *
44147836SJohn.Forte@Sun.COM  * Purpose - issues the ioctl to load the target groups into stmf
44157836SJohn.Forte@Sun.COM  *
44167836SJohn.Forte@Sun.COM  * fd - file descriptor for the control node of stmf.
44177836SJohn.Forte@Sun.COM  * groupList - populated target group list.
44187836SJohn.Forte@Sun.COM  */
44197836SJohn.Forte@Sun.COM static int
44207836SJohn.Forte@Sun.COM loadTargetGroups(int fd, stmfGroupList *groupList)
44217836SJohn.Forte@Sun.COM {
44227836SJohn.Forte@Sun.COM 	int i, j;
44237836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
44247836SJohn.Forte@Sun.COM 	stmfGroupProperties *groupProps = NULL;
44257836SJohn.Forte@Sun.COM 
44267836SJohn.Forte@Sun.COM 	for (i = 0; i < groupList->cnt; i++) {
44277836SJohn.Forte@Sun.COM 		if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_TARGET_GROUP,
44287836SJohn.Forte@Sun.COM 		    &(groupList->name[i]))) != STMF_STATUS_SUCCESS) {
44297836SJohn.Forte@Sun.COM 			goto out;
44307836SJohn.Forte@Sun.COM 		}
4431*9585STim.Szeto@Sun.COM 		ret = iLoadGroupMembersFromPs(&(groupList->name[i]),
4432*9585STim.Szeto@Sun.COM 		    &groupProps, TARGET_GROUP);
44337836SJohn.Forte@Sun.COM 		for (j = 0; j < groupProps->cnt; j++) {
44347836SJohn.Forte@Sun.COM 			if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_TG_ENTRY,
44357836SJohn.Forte@Sun.COM 			    &(groupList->name[i]), &(groupProps->name[j])))
44367836SJohn.Forte@Sun.COM 			    != STMF_STATUS_SUCCESS) {
44377836SJohn.Forte@Sun.COM 				goto out;
44387836SJohn.Forte@Sun.COM 			}
44397836SJohn.Forte@Sun.COM 		}
44407836SJohn.Forte@Sun.COM 	}
44417836SJohn.Forte@Sun.COM 
44427836SJohn.Forte@Sun.COM 
44437836SJohn.Forte@Sun.COM out:
44447836SJohn.Forte@Sun.COM 	stmfFreeMemory(groupProps);
44457836SJohn.Forte@Sun.COM 	return (ret);
44467836SJohn.Forte@Sun.COM }
44477836SJohn.Forte@Sun.COM 
44487836SJohn.Forte@Sun.COM 
44497836SJohn.Forte@Sun.COM /*
44507836SJohn.Forte@Sun.COM  * loadStore
44517836SJohn.Forte@Sun.COM  *
44527836SJohn.Forte@Sun.COM  * Purpose: Load the configuration data from the store
44537836SJohn.Forte@Sun.COM  *
44547836SJohn.Forte@Sun.COM  * First load the host groups and target groups, then the view entries
44557836SJohn.Forte@Sun.COM  * and finally the provider data
44567836SJohn.Forte@Sun.COM  *
44577836SJohn.Forte@Sun.COM  * fd - file descriptor of control node for stmf.
44587836SJohn.Forte@Sun.COM  */
44597836SJohn.Forte@Sun.COM static int
44607836SJohn.Forte@Sun.COM loadStore(int fd)
44617836SJohn.Forte@Sun.COM {
44627836SJohn.Forte@Sun.COM 	int ret;
44637836SJohn.Forte@Sun.COM 	int i, j;
44647836SJohn.Forte@Sun.COM 	stmfGroupList *groupList = NULL;
44657836SJohn.Forte@Sun.COM 	stmfGuidList *guidList = NULL;
44667836SJohn.Forte@Sun.COM 	stmfViewEntryList *viewEntryList = NULL;
44677836SJohn.Forte@Sun.COM 	stmfProviderList *providerList = NULL;
44687836SJohn.Forte@Sun.COM 	int providerType;
44697836SJohn.Forte@Sun.COM 	nvlist_t *nvl = NULL;
44707836SJohn.Forte@Sun.COM 
44717836SJohn.Forte@Sun.COM 
44727836SJohn.Forte@Sun.COM 
44737836SJohn.Forte@Sun.COM 	/* load host groups */
4474*9585STim.Szeto@Sun.COM 	ret = iLoadGroupFromPs(&groupList, HOST_GROUP);
44757836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
44767836SJohn.Forte@Sun.COM 		return (ret);
44777836SJohn.Forte@Sun.COM 	}
44787836SJohn.Forte@Sun.COM 	ret = loadHostGroups(fd, groupList);
44797836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
44807836SJohn.Forte@Sun.COM 		goto out;
44817836SJohn.Forte@Sun.COM 	}
44827836SJohn.Forte@Sun.COM 
44837836SJohn.Forte@Sun.COM 	stmfFreeMemory(groupList);
44847836SJohn.Forte@Sun.COM 	groupList = NULL;
44857836SJohn.Forte@Sun.COM 
44867836SJohn.Forte@Sun.COM 	/* load target groups */
4487*9585STim.Szeto@Sun.COM 	ret = iLoadGroupFromPs(&groupList, TARGET_GROUP);
44887836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
44897836SJohn.Forte@Sun.COM 		goto out;
44907836SJohn.Forte@Sun.COM 	}
44917836SJohn.Forte@Sun.COM 	ret = loadTargetGroups(fd, groupList);
44927836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
44937836SJohn.Forte@Sun.COM 		goto out;
44947836SJohn.Forte@Sun.COM 	}
44957836SJohn.Forte@Sun.COM 
44967836SJohn.Forte@Sun.COM 	stmfFreeMemory(groupList);
44977836SJohn.Forte@Sun.COM 	groupList = NULL;
44987836SJohn.Forte@Sun.COM 
44997836SJohn.Forte@Sun.COM 	/* Get the guid list */
45007836SJohn.Forte@Sun.COM 	ret = psGetLogicalUnitList(&guidList);
45017836SJohn.Forte@Sun.COM 	switch (ret) {
45027836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
45037836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
45047836SJohn.Forte@Sun.COM 			break;
45057836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
45067836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
45077836SJohn.Forte@Sun.COM 			break;
45087836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
45097836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
45107836SJohn.Forte@Sun.COM 			break;
45117836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
45127836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
45137836SJohn.Forte@Sun.COM 			break;
45147836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
45157836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
45167836SJohn.Forte@Sun.COM 			break;
45177836SJohn.Forte@Sun.COM 		default:
45187836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
45197836SJohn.Forte@Sun.COM 			break;
45207836SJohn.Forte@Sun.COM 	}
45217836SJohn.Forte@Sun.COM 
45227836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
45237836SJohn.Forte@Sun.COM 		goto out;
45247836SJohn.Forte@Sun.COM 	}
45257836SJohn.Forte@Sun.COM 
45267836SJohn.Forte@Sun.COM 	/*
45277836SJohn.Forte@Sun.COM 	 * We have the guid list, now get the corresponding
45287836SJohn.Forte@Sun.COM 	 * view entries for each guid
45297836SJohn.Forte@Sun.COM 	 */
45307836SJohn.Forte@Sun.COM 	for (i = 0; i < guidList->cnt; i++) {
45317836SJohn.Forte@Sun.COM 		ret = psGetViewEntryList(&guidList->guid[i], &viewEntryList);
45327836SJohn.Forte@Sun.COM 		switch (ret) {
45337836SJohn.Forte@Sun.COM 			case STMF_PS_SUCCESS:
45347836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_SUCCESS;
45357836SJohn.Forte@Sun.COM 				break;
45367836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_NOT_FOUND:
45377836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
45387836SJohn.Forte@Sun.COM 				break;
45397836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_BUSY:
45407836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
45417836SJohn.Forte@Sun.COM 				break;
45427836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_SERVICE_NOT_FOUND:
45437836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_SERVICE_NOT_FOUND;
45447836SJohn.Forte@Sun.COM 				break;
45457836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_VERSION_MISMATCH:
45467836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_SERVICE_DATA_VERSION;
45477836SJohn.Forte@Sun.COM 				break;
45487836SJohn.Forte@Sun.COM 			default:
45497836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
45507836SJohn.Forte@Sun.COM 				break;
45517836SJohn.Forte@Sun.COM 		}
45527836SJohn.Forte@Sun.COM 		if (ret != STMF_STATUS_SUCCESS) {
45537836SJohn.Forte@Sun.COM 			goto out;
45547836SJohn.Forte@Sun.COM 		}
45557836SJohn.Forte@Sun.COM 		for (j = 0; j < viewEntryList->cnt; j++) {
45567836SJohn.Forte@Sun.COM 			ret = addViewEntryIoctl(fd, &guidList->guid[i],
45577836SJohn.Forte@Sun.COM 			    &viewEntryList->ve[j]);
45587836SJohn.Forte@Sun.COM 			if (ret != STMF_STATUS_SUCCESS) {
45597836SJohn.Forte@Sun.COM 				goto out;
45607836SJohn.Forte@Sun.COM 			}
45617836SJohn.Forte@Sun.COM 		}
45627836SJohn.Forte@Sun.COM 	}
45637836SJohn.Forte@Sun.COM 
45647836SJohn.Forte@Sun.COM 	/* get the list of providers that have data */
45657836SJohn.Forte@Sun.COM 	ret = psGetProviderDataList(&providerList);
45667836SJohn.Forte@Sun.COM 	switch (ret) {
45677836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
45687836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
45697836SJohn.Forte@Sun.COM 			break;
45707836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
45717836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
45727836SJohn.Forte@Sun.COM 			break;
45737836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
45747836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
45757836SJohn.Forte@Sun.COM 			break;
45767836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
45777836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
45787836SJohn.Forte@Sun.COM 			break;
45797836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
45807836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
45817836SJohn.Forte@Sun.COM 			break;
45827836SJohn.Forte@Sun.COM 		default:
45837836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
45847836SJohn.Forte@Sun.COM 			break;
45857836SJohn.Forte@Sun.COM 	}
45867836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
45877836SJohn.Forte@Sun.COM 		goto out;
45887836SJohn.Forte@Sun.COM 	}
45897836SJohn.Forte@Sun.COM 
45907836SJohn.Forte@Sun.COM 	for (i = 0; i < providerList->cnt; i++) {
45917836SJohn.Forte@Sun.COM 		providerType = providerList->provider[i].providerType;
45927836SJohn.Forte@Sun.COM 		ret = psGetProviderData(providerList->provider[i].name,
45937836SJohn.Forte@Sun.COM 		    &nvl, providerType, NULL);
45947836SJohn.Forte@Sun.COM 		switch (ret) {
45957836SJohn.Forte@Sun.COM 			case STMF_PS_SUCCESS:
45967836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_SUCCESS;
45977836SJohn.Forte@Sun.COM 				break;
45987836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_NOT_FOUND:
45997836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
46007836SJohn.Forte@Sun.COM 				break;
46017836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_BUSY:
46027836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
46037836SJohn.Forte@Sun.COM 				break;
46047836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_SERVICE_NOT_FOUND:
46057836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_SERVICE_NOT_FOUND;
46067836SJohn.Forte@Sun.COM 				break;
46077836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_VERSION_MISMATCH:
46087836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_SERVICE_DATA_VERSION;
46097836SJohn.Forte@Sun.COM 				break;
46107836SJohn.Forte@Sun.COM 			default:
46117836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
46127836SJohn.Forte@Sun.COM 				break;
46137836SJohn.Forte@Sun.COM 		}
46147836SJohn.Forte@Sun.COM 		if (ret != STMF_STATUS_SUCCESS) {
46157836SJohn.Forte@Sun.COM 			goto out;
46167836SJohn.Forte@Sun.COM 		}
46177836SJohn.Forte@Sun.COM 
46187836SJohn.Forte@Sun.COM 		/* call setProviderData */
46197836SJohn.Forte@Sun.COM 		ret = setProviderData(fd, providerList->provider[i].name, nvl,
4620*9585STim.Szeto@Sun.COM 		    providerType, NULL);
46217836SJohn.Forte@Sun.COM 		switch (ret) {
46227836SJohn.Forte@Sun.COM 			case STMF_PS_SUCCESS:
46237836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_SUCCESS;
46247836SJohn.Forte@Sun.COM 				break;
46257836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_NOT_FOUND:
46267836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
46277836SJohn.Forte@Sun.COM 				break;
46287836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_BUSY:
46297836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
46307836SJohn.Forte@Sun.COM 				break;
46317836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_SERVICE_NOT_FOUND:
46327836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_SERVICE_NOT_FOUND;
46337836SJohn.Forte@Sun.COM 				break;
46347836SJohn.Forte@Sun.COM 			case STMF_PS_ERROR_VERSION_MISMATCH:
46357836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_SERVICE_DATA_VERSION;
46367836SJohn.Forte@Sun.COM 				break;
46377836SJohn.Forte@Sun.COM 			default:
46387836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
46397836SJohn.Forte@Sun.COM 				break;
46407836SJohn.Forte@Sun.COM 		}
46417836SJohn.Forte@Sun.COM 		if (ret != STMF_STATUS_SUCCESS) {
46427836SJohn.Forte@Sun.COM 			goto out;
46437836SJohn.Forte@Sun.COM 		}
46447836SJohn.Forte@Sun.COM 
46457836SJohn.Forte@Sun.COM 		nvlist_free(nvl);
46467836SJohn.Forte@Sun.COM 		nvl = NULL;
46477836SJohn.Forte@Sun.COM 	}
46487836SJohn.Forte@Sun.COM out:
46497836SJohn.Forte@Sun.COM 	if (groupList != NULL) {
46507836SJohn.Forte@Sun.COM 		free(groupList);
46517836SJohn.Forte@Sun.COM 	}
46527836SJohn.Forte@Sun.COM 	if (guidList != NULL) {
46537836SJohn.Forte@Sun.COM 		free(guidList);
46547836SJohn.Forte@Sun.COM 	}
46557836SJohn.Forte@Sun.COM 	if (viewEntryList != NULL) {
46567836SJohn.Forte@Sun.COM 		free(viewEntryList);
46577836SJohn.Forte@Sun.COM 	}
46587836SJohn.Forte@Sun.COM 	if (nvl != NULL) {
46597836SJohn.Forte@Sun.COM 		nvlist_free(nvl);
46607836SJohn.Forte@Sun.COM 	}
46617836SJohn.Forte@Sun.COM 	return (ret);
46627836SJohn.Forte@Sun.COM }
46637836SJohn.Forte@Sun.COM 
46647836SJohn.Forte@Sun.COM /*
46657836SJohn.Forte@Sun.COM  * stmfLoadConfig
46667836SJohn.Forte@Sun.COM  *
46677836SJohn.Forte@Sun.COM  * Purpose - load the configuration data from smf into stmf
46687836SJohn.Forte@Sun.COM  *
46697836SJohn.Forte@Sun.COM  */
46707836SJohn.Forte@Sun.COM int
46717836SJohn.Forte@Sun.COM stmfLoadConfig(void)
46727836SJohn.Forte@Sun.COM {
4673*9585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
46747836SJohn.Forte@Sun.COM 	int fd;
46757836SJohn.Forte@Sun.COM 	stmf_state_desc_t stmfStateSet;
46767836SJohn.Forte@Sun.COM 	stmfState state;
46777836SJohn.Forte@Sun.COM 
4678*9585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
4679*9585STim.Szeto@Sun.COM 		stmfStateSet.state = STMF_STATE_OFFLINE;
4680*9585STim.Szeto@Sun.COM 		stmfStateSet.config_state = STMF_CONFIG_INIT;
4681*9585STim.Szeto@Sun.COM 		if ((ret = openStmf(OPEN_EXCL_STMF, &fd))
4682*9585STim.Szeto@Sun.COM 		    != STMF_STATUS_SUCCESS) {
4683*9585STim.Szeto@Sun.COM 			return (ret);
4684*9585STim.Szeto@Sun.COM 		}
4685*9585STim.Szeto@Sun.COM 		ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE);
4686*9585STim.Szeto@Sun.COM 		if (ret != STMF_STATUS_SUCCESS) {
4687*9585STim.Szeto@Sun.COM 			goto done;
4688*9585STim.Szeto@Sun.COM 		}
4689*9585STim.Szeto@Sun.COM 		stmfStateSet.config_state = STMF_CONFIG_INIT_DONE;
4690*9585STim.Szeto@Sun.COM 		goto done;
4691*9585STim.Szeto@Sun.COM 	}
46927836SJohn.Forte@Sun.COM 
46937836SJohn.Forte@Sun.COM 	/* Check to ensure service exists */
46947836SJohn.Forte@Sun.COM 	if (psCheckService() != STMF_STATUS_SUCCESS) {
46957836SJohn.Forte@Sun.COM 		return (STMF_ERROR_SERVICE_NOT_FOUND);
46967836SJohn.Forte@Sun.COM 	}
46977836SJohn.Forte@Sun.COM 
46987836SJohn.Forte@Sun.COM 	ret = stmfGetState(&state);
46997836SJohn.Forte@Sun.COM 	if (ret == STMF_STATUS_SUCCESS) {
47007836SJohn.Forte@Sun.COM 		if (state.operationalState != STMF_SERVICE_STATE_OFFLINE) {
47017836SJohn.Forte@Sun.COM 			return (STMF_ERROR_SERVICE_ONLINE);
47027836SJohn.Forte@Sun.COM 		}
47037836SJohn.Forte@Sun.COM 	} else {
47047836SJohn.Forte@Sun.COM 		return (STMF_STATUS_ERROR);
47057836SJohn.Forte@Sun.COM 	}
47067836SJohn.Forte@Sun.COM 
47077836SJohn.Forte@Sun.COM 
47087836SJohn.Forte@Sun.COM 	stmfStateSet.state = STMF_STATE_OFFLINE;
47097836SJohn.Forte@Sun.COM 	stmfStateSet.config_state = STMF_CONFIG_INIT;
47107836SJohn.Forte@Sun.COM 
47117836SJohn.Forte@Sun.COM 	/*
47127836SJohn.Forte@Sun.COM 	 * Open control node for stmf
47137836SJohn.Forte@Sun.COM 	 */
47147836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
47157836SJohn.Forte@Sun.COM 		return (ret);
47167836SJohn.Forte@Sun.COM 
47177836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE);
47187836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
47197836SJohn.Forte@Sun.COM 		goto done;
47207836SJohn.Forte@Sun.COM 	}
47217836SJohn.Forte@Sun.COM 
47227836SJohn.Forte@Sun.COM 	/* Load the persistent configuration data */
47237836SJohn.Forte@Sun.COM 	ret = loadStore(fd);
47247836SJohn.Forte@Sun.COM 	if (ret != 0) {
47257836SJohn.Forte@Sun.COM 		goto done;
47267836SJohn.Forte@Sun.COM 	}
47277836SJohn.Forte@Sun.COM 
47287836SJohn.Forte@Sun.COM 	stmfStateSet.state = STMF_STATE_OFFLINE;
47297836SJohn.Forte@Sun.COM 	stmfStateSet.config_state = STMF_CONFIG_INIT_DONE;
47307836SJohn.Forte@Sun.COM 
47317836SJohn.Forte@Sun.COM done:
47327836SJohn.Forte@Sun.COM 	if (ret == STMF_STATUS_SUCCESS) {
47337836SJohn.Forte@Sun.COM 		ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE);
47347836SJohn.Forte@Sun.COM 	}
47357836SJohn.Forte@Sun.COM 	(void) close(fd);
47367836SJohn.Forte@Sun.COM 	return (ret);
47377836SJohn.Forte@Sun.COM }
47387836SJohn.Forte@Sun.COM 
4739*9585STim.Szeto@Sun.COM 
47407836SJohn.Forte@Sun.COM /*
47417836SJohn.Forte@Sun.COM  * getStmfState
47427836SJohn.Forte@Sun.COM  *
47437836SJohn.Forte@Sun.COM  * stmfState - pointer to stmf_state_desc_t structure. Will contain the state
47447836SJohn.Forte@Sun.COM  *             information of the stmf service on success.
47457836SJohn.Forte@Sun.COM  */
47467836SJohn.Forte@Sun.COM static int
47477836SJohn.Forte@Sun.COM getStmfState(stmf_state_desc_t *stmfState)
47487836SJohn.Forte@Sun.COM {
47497836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
47507836SJohn.Forte@Sun.COM 	int fd;
47517836SJohn.Forte@Sun.COM 	int ioctlRet;
47527836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
47537836SJohn.Forte@Sun.COM 
47547836SJohn.Forte@Sun.COM 	/*
47557836SJohn.Forte@Sun.COM 	 * Open control node for stmf
47567836SJohn.Forte@Sun.COM 	 */
47577836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
47587836SJohn.Forte@Sun.COM 		return (ret);
47597836SJohn.Forte@Sun.COM 
47607836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
47617836SJohn.Forte@Sun.COM 	/*
47627836SJohn.Forte@Sun.COM 	 * Issue ioctl to get the stmf state
47637836SJohn.Forte@Sun.COM 	 */
47647836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
47657836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (stmf_state_desc_t);
47667836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)stmfState;
47677836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf_size = sizeof (stmf_state_desc_t);
47687836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)stmfState;
47697836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_GET_STMF_STATE, &stmfIoctl);
47707836SJohn.Forte@Sun.COM 
47717836SJohn.Forte@Sun.COM 	(void) close(fd);
47727836SJohn.Forte@Sun.COM 
47737836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
47747836SJohn.Forte@Sun.COM 		switch (errno) {
47757836SJohn.Forte@Sun.COM 			case EBUSY:
47767836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
47777836SJohn.Forte@Sun.COM 				break;
47787836SJohn.Forte@Sun.COM 			case EPERM:
47797836SJohn.Forte@Sun.COM 			case EACCES:
47807836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
47817836SJohn.Forte@Sun.COM 				break;
47827836SJohn.Forte@Sun.COM 			default:
47837836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
47847836SJohn.Forte@Sun.COM 				    "getStmfState:ioctl errno(%d)", errno);
47857836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
47867836SJohn.Forte@Sun.COM 				break;
47877836SJohn.Forte@Sun.COM 		}
47887836SJohn.Forte@Sun.COM 	}
47897836SJohn.Forte@Sun.COM 	return (ret);
47907836SJohn.Forte@Sun.COM }
47917836SJohn.Forte@Sun.COM 
47927836SJohn.Forte@Sun.COM 
47937836SJohn.Forte@Sun.COM /*
47947836SJohn.Forte@Sun.COM  * setStmfState
47957836SJohn.Forte@Sun.COM  *
47967836SJohn.Forte@Sun.COM  * stmfState - pointer to caller set state structure
47977836SJohn.Forte@Sun.COM  * objectType - one of:
47987836SJohn.Forte@Sun.COM  *		LOGICAL_UNIT_TYPE
47997836SJohn.Forte@Sun.COM  *		TARGET_TYPE
48007836SJohn.Forte@Sun.COM  *		STMF_SERVICE_TYPE
48017836SJohn.Forte@Sun.COM  */
48027836SJohn.Forte@Sun.COM static int
48037836SJohn.Forte@Sun.COM setStmfState(int fd, stmf_state_desc_t *stmfState, int objectType)
48047836SJohn.Forte@Sun.COM {
48057836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
48067836SJohn.Forte@Sun.COM 	int ioctlRet;
48077836SJohn.Forte@Sun.COM 	int cmd;
48087836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
48097836SJohn.Forte@Sun.COM 
48107836SJohn.Forte@Sun.COM 	switch (objectType) {
48117836SJohn.Forte@Sun.COM 		case LOGICAL_UNIT_TYPE:
48127836SJohn.Forte@Sun.COM 			cmd = STMF_IOCTL_SET_LU_STATE;
48137836SJohn.Forte@Sun.COM 			break;
48147836SJohn.Forte@Sun.COM 		case TARGET_TYPE:
48157836SJohn.Forte@Sun.COM 			cmd = STMF_IOCTL_SET_TARGET_PORT_STATE;
48167836SJohn.Forte@Sun.COM 			break;
48177836SJohn.Forte@Sun.COM 		case STMF_SERVICE_TYPE:
48187836SJohn.Forte@Sun.COM 			cmd = STMF_IOCTL_SET_STMF_STATE;
48197836SJohn.Forte@Sun.COM 			break;
48207836SJohn.Forte@Sun.COM 		default:
48217836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
48227836SJohn.Forte@Sun.COM 			goto done;
48237836SJohn.Forte@Sun.COM 	}
48247836SJohn.Forte@Sun.COM 
48257836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
48267836SJohn.Forte@Sun.COM 	/*
48277836SJohn.Forte@Sun.COM 	 * Issue ioctl to set the stmf state
48287836SJohn.Forte@Sun.COM 	 */
48297836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
48307836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (stmf_state_desc_t);
48317836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)stmfState;
48327836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
48337836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
48347836SJohn.Forte@Sun.COM 		switch (errno) {
48357836SJohn.Forte@Sun.COM 			case EBUSY:
48367836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
48377836SJohn.Forte@Sun.COM 				break;
4838*9585STim.Szeto@Sun.COM 			case EPERM:
48397836SJohn.Forte@Sun.COM 			case EACCES:
48407836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
48417836SJohn.Forte@Sun.COM 				break;
48427836SJohn.Forte@Sun.COM 			case ENOENT:
48437836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
48447836SJohn.Forte@Sun.COM 				break;
48457836SJohn.Forte@Sun.COM 			default:
48467836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
48477836SJohn.Forte@Sun.COM 				    "setStmfState:ioctl errno(%d)", errno);
48487836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
48497836SJohn.Forte@Sun.COM 				break;
48507836SJohn.Forte@Sun.COM 		}
48517836SJohn.Forte@Sun.COM 	}
48527836SJohn.Forte@Sun.COM done:
48537836SJohn.Forte@Sun.COM 	return (ret);
48547836SJohn.Forte@Sun.COM }
48557836SJohn.Forte@Sun.COM 
48567836SJohn.Forte@Sun.COM /*
48577836SJohn.Forte@Sun.COM  * stmfOnline
48587836SJohn.Forte@Sun.COM  *
48597836SJohn.Forte@Sun.COM  * Purpose: Online stmf service
48607836SJohn.Forte@Sun.COM  *
48617836SJohn.Forte@Sun.COM  */
48627836SJohn.Forte@Sun.COM int
48637836SJohn.Forte@Sun.COM stmfOnline(void)
48647836SJohn.Forte@Sun.COM {
48657836SJohn.Forte@Sun.COM 	int ret;
48667836SJohn.Forte@Sun.COM 	int fd;
48677836SJohn.Forte@Sun.COM 	stmfState state;
48687836SJohn.Forte@Sun.COM 	stmf_state_desc_t iState;
48697836SJohn.Forte@Sun.COM 
48707836SJohn.Forte@Sun.COM 	ret = stmfGetState(&state);
48717836SJohn.Forte@Sun.COM 	if (ret == STMF_STATUS_SUCCESS) {
48727836SJohn.Forte@Sun.COM 		if (state.operationalState == STMF_SERVICE_STATE_ONLINE) {
48737836SJohn.Forte@Sun.COM 			return (STMF_ERROR_SERVICE_ONLINE);
48747836SJohn.Forte@Sun.COM 		}
48757836SJohn.Forte@Sun.COM 	} else {
48767836SJohn.Forte@Sun.COM 		return (STMF_STATUS_ERROR);
48777836SJohn.Forte@Sun.COM 	}
48787836SJohn.Forte@Sun.COM 	iState.state = STMF_STATE_ONLINE;
48797836SJohn.Forte@Sun.COM 	iState.config_state = STMF_CONFIG_NONE;
48807836SJohn.Forte@Sun.COM 	/*
48817836SJohn.Forte@Sun.COM 	 * Open control node for stmf
48827836SJohn.Forte@Sun.COM 	 * to make call to setStmfState()
48837836SJohn.Forte@Sun.COM 	 */
48847836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
48857836SJohn.Forte@Sun.COM 		return (ret);
48867836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &iState, STMF_SERVICE_TYPE);
48877836SJohn.Forte@Sun.COM 	(void) close(fd);
48887836SJohn.Forte@Sun.COM 	return (ret);
48897836SJohn.Forte@Sun.COM }
48907836SJohn.Forte@Sun.COM 
48917836SJohn.Forte@Sun.COM /*
48927836SJohn.Forte@Sun.COM  * stmfOffline
48937836SJohn.Forte@Sun.COM  *
48947836SJohn.Forte@Sun.COM  * Purpose: Offline stmf service
48957836SJohn.Forte@Sun.COM  *
48967836SJohn.Forte@Sun.COM  */
48977836SJohn.Forte@Sun.COM int
48987836SJohn.Forte@Sun.COM stmfOffline(void)
48997836SJohn.Forte@Sun.COM {
49007836SJohn.Forte@Sun.COM 	int ret;
49017836SJohn.Forte@Sun.COM 	int fd;
49027836SJohn.Forte@Sun.COM 	stmfState state;
49037836SJohn.Forte@Sun.COM 	stmf_state_desc_t iState;
49047836SJohn.Forte@Sun.COM 
49057836SJohn.Forte@Sun.COM 	ret = stmfGetState(&state);
49067836SJohn.Forte@Sun.COM 	if (ret == STMF_STATUS_SUCCESS) {
49077836SJohn.Forte@Sun.COM 		if (state.operationalState == STMF_SERVICE_STATE_OFFLINE) {
49087836SJohn.Forte@Sun.COM 			return (STMF_ERROR_SERVICE_OFFLINE);
49097836SJohn.Forte@Sun.COM 		}
49107836SJohn.Forte@Sun.COM 	} else {
49117836SJohn.Forte@Sun.COM 		return (STMF_STATUS_ERROR);
49127836SJohn.Forte@Sun.COM 	}
49137836SJohn.Forte@Sun.COM 	iState.state = STMF_STATE_OFFLINE;
49147836SJohn.Forte@Sun.COM 	iState.config_state = STMF_CONFIG_NONE;
49157836SJohn.Forte@Sun.COM 
49167836SJohn.Forte@Sun.COM 	/*
49177836SJohn.Forte@Sun.COM 	 * Open control node for stmf
49187836SJohn.Forte@Sun.COM 	 * to make call to setStmfState()
49197836SJohn.Forte@Sun.COM 	 */
49207836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
49217836SJohn.Forte@Sun.COM 		return (ret);
49227836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &iState, STMF_SERVICE_TYPE);
49237836SJohn.Forte@Sun.COM 	(void) close(fd);
49247836SJohn.Forte@Sun.COM 	return (ret);
49257836SJohn.Forte@Sun.COM }
49267836SJohn.Forte@Sun.COM 
49277836SJohn.Forte@Sun.COM 
49287836SJohn.Forte@Sun.COM /*
49297836SJohn.Forte@Sun.COM  * stmfOfflineTarget
49307836SJohn.Forte@Sun.COM  *
49317836SJohn.Forte@Sun.COM  * Purpose: Change state of target to offline
49327836SJohn.Forte@Sun.COM  *
49337836SJohn.Forte@Sun.COM  * devid - devid of the target to offline
49347836SJohn.Forte@Sun.COM  */
49357836SJohn.Forte@Sun.COM int
49367836SJohn.Forte@Sun.COM stmfOfflineTarget(stmfDevid *devid)
49377836SJohn.Forte@Sun.COM {
49387836SJohn.Forte@Sun.COM 	stmf_state_desc_t targetState;
49397836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
49407836SJohn.Forte@Sun.COM 	int fd;
49417836SJohn.Forte@Sun.COM 
49427836SJohn.Forte@Sun.COM 	if (devid == NULL) {
49437836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
49447836SJohn.Forte@Sun.COM 	}
49457836SJohn.Forte@Sun.COM 	bzero(&targetState, sizeof (targetState));
49467836SJohn.Forte@Sun.COM 
49477836SJohn.Forte@Sun.COM 	targetState.state = STMF_STATE_OFFLINE;
49487836SJohn.Forte@Sun.COM 	targetState.ident[IDENT_LENGTH_BYTE] = devid->identLength;
49497836SJohn.Forte@Sun.COM 	bcopy(&(devid->ident), &targetState.ident[IDENT_LENGTH_BYTE + 1],
49507836SJohn.Forte@Sun.COM 	    devid->identLength);
49517836SJohn.Forte@Sun.COM 	/*
49527836SJohn.Forte@Sun.COM 	 * Open control node for stmf
49537836SJohn.Forte@Sun.COM 	 * to make call to setStmfState()
49547836SJohn.Forte@Sun.COM 	 */
49557836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
49567836SJohn.Forte@Sun.COM 		return (ret);
49577836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &targetState, TARGET_TYPE);
49587836SJohn.Forte@Sun.COM 	(void) close(fd);
49597836SJohn.Forte@Sun.COM 	return (ret);
49607836SJohn.Forte@Sun.COM }
49617836SJohn.Forte@Sun.COM 
49627836SJohn.Forte@Sun.COM /*
49637836SJohn.Forte@Sun.COM  * stmfOfflineLogicalUnit
49647836SJohn.Forte@Sun.COM  *
49657836SJohn.Forte@Sun.COM  * Purpose: Change state of logical unit to offline
49667836SJohn.Forte@Sun.COM  *
49677836SJohn.Forte@Sun.COM  * lu - guid of the logical unit to offline
49687836SJohn.Forte@Sun.COM  */
49697836SJohn.Forte@Sun.COM int
49707836SJohn.Forte@Sun.COM stmfOfflineLogicalUnit(stmfGuid *lu)
49717836SJohn.Forte@Sun.COM {
49727836SJohn.Forte@Sun.COM 	stmf_state_desc_t luState;
49737836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
49747836SJohn.Forte@Sun.COM 	int fd;
49757836SJohn.Forte@Sun.COM 
49767836SJohn.Forte@Sun.COM 	if (lu == NULL) {
49777836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
49787836SJohn.Forte@Sun.COM 	}
49797836SJohn.Forte@Sun.COM 
49807836SJohn.Forte@Sun.COM 	bzero(&luState, sizeof (luState));
49817836SJohn.Forte@Sun.COM 
49827836SJohn.Forte@Sun.COM 	luState.state = STMF_STATE_OFFLINE;
49837836SJohn.Forte@Sun.COM 	bcopy(lu, &luState.ident, sizeof (stmfGuid));
49847836SJohn.Forte@Sun.COM 	/*
49857836SJohn.Forte@Sun.COM 	 * Open control node for stmf
49867836SJohn.Forte@Sun.COM 	 * to make call to setStmfState()
49877836SJohn.Forte@Sun.COM 	 */
49887836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
49897836SJohn.Forte@Sun.COM 		return (ret);
49907836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &luState, LOGICAL_UNIT_TYPE);
49917836SJohn.Forte@Sun.COM 	(void) close(fd);
49927836SJohn.Forte@Sun.COM 	return (ret);
49937836SJohn.Forte@Sun.COM }
49947836SJohn.Forte@Sun.COM 
49957836SJohn.Forte@Sun.COM /*
49967836SJohn.Forte@Sun.COM  * stmfOnlineTarget
49977836SJohn.Forte@Sun.COM  *
49987836SJohn.Forte@Sun.COM  * Purpose: Change state of target to online
49997836SJohn.Forte@Sun.COM  *
50007836SJohn.Forte@Sun.COM  * devid - devid of the target to online
50017836SJohn.Forte@Sun.COM  */
50027836SJohn.Forte@Sun.COM int
50037836SJohn.Forte@Sun.COM stmfOnlineTarget(stmfDevid *devid)
50047836SJohn.Forte@Sun.COM {
50057836SJohn.Forte@Sun.COM 	stmf_state_desc_t targetState;
50067836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
50077836SJohn.Forte@Sun.COM 	int fd;
50087836SJohn.Forte@Sun.COM 
50097836SJohn.Forte@Sun.COM 	if (devid == NULL) {
50107836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
50117836SJohn.Forte@Sun.COM 	}
50127836SJohn.Forte@Sun.COM 	bzero(&targetState, sizeof (targetState));
50137836SJohn.Forte@Sun.COM 
50147836SJohn.Forte@Sun.COM 	targetState.state = STMF_STATE_ONLINE;
50157836SJohn.Forte@Sun.COM 	targetState.ident[IDENT_LENGTH_BYTE] = devid->identLength;
50167836SJohn.Forte@Sun.COM 	bcopy(&(devid->ident), &targetState.ident[IDENT_LENGTH_BYTE + 1],
50177836SJohn.Forte@Sun.COM 	    devid->identLength);
50187836SJohn.Forte@Sun.COM 	/*
50197836SJohn.Forte@Sun.COM 	 * Open control node for stmf
50207836SJohn.Forte@Sun.COM 	 * to make call to setStmfState()
50217836SJohn.Forte@Sun.COM 	 */
50227836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
50237836SJohn.Forte@Sun.COM 		return (ret);
50247836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &targetState, TARGET_TYPE);
50257836SJohn.Forte@Sun.COM 	(void) close(fd);
50267836SJohn.Forte@Sun.COM 	return (ret);
50277836SJohn.Forte@Sun.COM }
50287836SJohn.Forte@Sun.COM 
50297836SJohn.Forte@Sun.COM /*
50307836SJohn.Forte@Sun.COM  * stmfOnlineLogicalUnit
50317836SJohn.Forte@Sun.COM  *
50327836SJohn.Forte@Sun.COM  * Purpose: Change state of logical unit to online
50337836SJohn.Forte@Sun.COM  *
50347836SJohn.Forte@Sun.COM  * lu - guid of the logical unit to online
50357836SJohn.Forte@Sun.COM  */
50367836SJohn.Forte@Sun.COM int
50377836SJohn.Forte@Sun.COM stmfOnlineLogicalUnit(stmfGuid *lu)
50387836SJohn.Forte@Sun.COM {
50397836SJohn.Forte@Sun.COM 	stmf_state_desc_t luState;
50407836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
50417836SJohn.Forte@Sun.COM 	int fd;
50427836SJohn.Forte@Sun.COM 
50437836SJohn.Forte@Sun.COM 	if (lu == NULL) {
50447836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
50457836SJohn.Forte@Sun.COM 	}
50467836SJohn.Forte@Sun.COM 
50477836SJohn.Forte@Sun.COM 	bzero(&luState, sizeof (luState));
50487836SJohn.Forte@Sun.COM 
50497836SJohn.Forte@Sun.COM 	luState.state = STMF_STATE_ONLINE;
50507836SJohn.Forte@Sun.COM 	bcopy(lu, &luState.ident, sizeof (stmfGuid));
50517836SJohn.Forte@Sun.COM 	/*
50527836SJohn.Forte@Sun.COM 	 * Open control node for stmf
50537836SJohn.Forte@Sun.COM 	 * to make call to setStmfState()
50547836SJohn.Forte@Sun.COM 	 */
50557836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
50567836SJohn.Forte@Sun.COM 		return (ret);
50577836SJohn.Forte@Sun.COM 	ret = setStmfState(fd, &luState, LOGICAL_UNIT_TYPE);
50587836SJohn.Forte@Sun.COM 	(void) close(fd);
50597836SJohn.Forte@Sun.COM 	return (ret);
50607836SJohn.Forte@Sun.COM }
50617836SJohn.Forte@Sun.COM 
50627836SJohn.Forte@Sun.COM /*
50637836SJohn.Forte@Sun.COM  * stmfRemoveFromHostGroup
50647836SJohn.Forte@Sun.COM  *
50657836SJohn.Forte@Sun.COM  * Purpose: Removes an initiator from an initiator group
50667836SJohn.Forte@Sun.COM  *
50677836SJohn.Forte@Sun.COM  * hostGroupName - name of an initiator group
50687836SJohn.Forte@Sun.COM  * hostName - name of host group member to remove
50697836SJohn.Forte@Sun.COM  */
50707836SJohn.Forte@Sun.COM int
50717836SJohn.Forte@Sun.COM stmfRemoveFromHostGroup(stmfGroupName *hostGroupName, stmfDevid *hostName)
50727836SJohn.Forte@Sun.COM {
50737836SJohn.Forte@Sun.COM 	int ret;
50747836SJohn.Forte@Sun.COM 	int fd;
50757836SJohn.Forte@Sun.COM 
50767836SJohn.Forte@Sun.COM 	if (hostGroupName == NULL ||
50777836SJohn.Forte@Sun.COM 	    (strnlen((char *)hostGroupName, sizeof (stmfGroupName))
50787836SJohn.Forte@Sun.COM 	    == sizeof (stmfGroupName)) || hostName == NULL) {
50797836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
50807836SJohn.Forte@Sun.COM 	}
50817836SJohn.Forte@Sun.COM 
50827836SJohn.Forte@Sun.COM 	/* call init */
50837836SJohn.Forte@Sun.COM 	ret = initializeConfig();
50847836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
50857836SJohn.Forte@Sun.COM 		return (ret);
50867836SJohn.Forte@Sun.COM 	}
50877836SJohn.Forte@Sun.COM 
50887836SJohn.Forte@Sun.COM 	/*
50897836SJohn.Forte@Sun.COM 	 * Open control node for stmf
50907836SJohn.Forte@Sun.COM 	 */
50917836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
50927836SJohn.Forte@Sun.COM 		return (ret);
50937836SJohn.Forte@Sun.COM 
50947836SJohn.Forte@Sun.COM 	if ((ret = groupMemberIoctl(fd, STMF_IOCTL_REMOVE_HG_ENTRY,
50957836SJohn.Forte@Sun.COM 	    hostGroupName, hostName)) != STMF_STATUS_SUCCESS) {
50967836SJohn.Forte@Sun.COM 		goto done;
50977836SJohn.Forte@Sun.COM 	}
50987836SJohn.Forte@Sun.COM 
5099*9585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
5100*9585STim.Szeto@Sun.COM 		goto done;
5101*9585STim.Szeto@Sun.COM 	}
5102*9585STim.Szeto@Sun.COM 
51037836SJohn.Forte@Sun.COM 	ret = psRemoveHostGroupMember((char *)hostGroupName,
51047836SJohn.Forte@Sun.COM 	    (char *)hostName->ident);
51057836SJohn.Forte@Sun.COM 	switch (ret) {
51067836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
51077836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
51087836SJohn.Forte@Sun.COM 			break;
51097836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_MEMBER_NOT_FOUND:
51107836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_MEMBER_NOT_FOUND;
51117836SJohn.Forte@Sun.COM 			break;
51127836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_GROUP_NOT_FOUND:
51137836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_GROUP_NOT_FOUND;
51147836SJohn.Forte@Sun.COM 			break;
51157836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
51167836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
51177836SJohn.Forte@Sun.COM 			break;
51187836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
51197836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
51207836SJohn.Forte@Sun.COM 			break;
51217836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
51227836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
51237836SJohn.Forte@Sun.COM 			break;
51247836SJohn.Forte@Sun.COM 		default:
51257836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
51267836SJohn.Forte@Sun.COM 			    "stmfRemoveFromHostGroup"
51277836SJohn.Forte@Sun.COM 			    "psRemoveHostGroupMember:error(%d)", ret);
51287836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
51297836SJohn.Forte@Sun.COM 			break;
51307836SJohn.Forte@Sun.COM 	}
51317836SJohn.Forte@Sun.COM 
51327836SJohn.Forte@Sun.COM done:
51337836SJohn.Forte@Sun.COM 	(void) close(fd);
51347836SJohn.Forte@Sun.COM 	return (ret);
51357836SJohn.Forte@Sun.COM }
51367836SJohn.Forte@Sun.COM 
51377836SJohn.Forte@Sun.COM /*
51387836SJohn.Forte@Sun.COM  * stmfRemoveFromTargetGroup
51397836SJohn.Forte@Sun.COM  *
51407836SJohn.Forte@Sun.COM  * Purpose: Removes a local port from a local port group
51417836SJohn.Forte@Sun.COM  *
51427836SJohn.Forte@Sun.COM  * targetGroupName - name of a target group
51437836SJohn.Forte@Sun.COM  * targetName - name of target to remove
51447836SJohn.Forte@Sun.COM  */
51457836SJohn.Forte@Sun.COM int
51467836SJohn.Forte@Sun.COM stmfRemoveFromTargetGroup(stmfGroupName *targetGroupName, stmfDevid *targetName)
51477836SJohn.Forte@Sun.COM {
51487836SJohn.Forte@Sun.COM 	int ret;
51497836SJohn.Forte@Sun.COM 	int fd;
51507836SJohn.Forte@Sun.COM 
51517836SJohn.Forte@Sun.COM 	if (targetGroupName == NULL ||
51527836SJohn.Forte@Sun.COM 	    (strnlen((char *)targetGroupName, sizeof (stmfGroupName))
51537836SJohn.Forte@Sun.COM 	    == sizeof (stmfGroupName)) || targetName == NULL) {
51547836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
51557836SJohn.Forte@Sun.COM 	}
51567836SJohn.Forte@Sun.COM 
51577836SJohn.Forte@Sun.COM 	/* call init */
51587836SJohn.Forte@Sun.COM 	ret = initializeConfig();
51597836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
51607836SJohn.Forte@Sun.COM 		return (ret);
51617836SJohn.Forte@Sun.COM 	}
51627836SJohn.Forte@Sun.COM 
51637836SJohn.Forte@Sun.COM 	/*
51647836SJohn.Forte@Sun.COM 	 * Open control node for stmf
51657836SJohn.Forte@Sun.COM 	 */
51667836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
51677836SJohn.Forte@Sun.COM 		return (ret);
51687836SJohn.Forte@Sun.COM 
51697836SJohn.Forte@Sun.COM 	if ((ret = groupMemberIoctl(fd, STMF_IOCTL_REMOVE_TG_ENTRY,
51707836SJohn.Forte@Sun.COM 	    targetGroupName, targetName)) != STMF_STATUS_SUCCESS) {
51717836SJohn.Forte@Sun.COM 		goto done;
51727836SJohn.Forte@Sun.COM 	}
51737836SJohn.Forte@Sun.COM 
5174*9585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
5175*9585STim.Szeto@Sun.COM 		goto done;
5176*9585STim.Szeto@Sun.COM 	}
5177*9585STim.Szeto@Sun.COM 
51787836SJohn.Forte@Sun.COM 	ret = psRemoveTargetGroupMember((char *)targetGroupName,
51797836SJohn.Forte@Sun.COM 	    (char *)targetName->ident);
51807836SJohn.Forte@Sun.COM 	switch (ret) {
51817836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
51827836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
51837836SJohn.Forte@Sun.COM 			break;
51847836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_MEMBER_NOT_FOUND:
51857836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_MEMBER_NOT_FOUND;
51867836SJohn.Forte@Sun.COM 			break;
51877836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_GROUP_NOT_FOUND:
51887836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_GROUP_NOT_FOUND;
51897836SJohn.Forte@Sun.COM 			break;
51907836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
51917836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
51927836SJohn.Forte@Sun.COM 			break;
51937836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
51947836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
51957836SJohn.Forte@Sun.COM 			break;
51967836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
51977836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
51987836SJohn.Forte@Sun.COM 			break;
51997836SJohn.Forte@Sun.COM 		default:
52007836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
52017836SJohn.Forte@Sun.COM 			    "stmfRemoveFromTargetGroup"
52027836SJohn.Forte@Sun.COM 			    "psRemoveTargetGroupMember:error(%d)", ret);
52037836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
52047836SJohn.Forte@Sun.COM 			break;
52057836SJohn.Forte@Sun.COM 	}
52067836SJohn.Forte@Sun.COM 
52077836SJohn.Forte@Sun.COM done:
52087836SJohn.Forte@Sun.COM 	(void) close(fd);
52097836SJohn.Forte@Sun.COM 	return (ret);
52107836SJohn.Forte@Sun.COM }
52117836SJohn.Forte@Sun.COM 
52127836SJohn.Forte@Sun.COM /*
52137836SJohn.Forte@Sun.COM  * stmfRemoveViewEntry
52147836SJohn.Forte@Sun.COM  *
52157836SJohn.Forte@Sun.COM  * Purpose: Removes a view entry from a logical unit
52167836SJohn.Forte@Sun.COM  *
52177836SJohn.Forte@Sun.COM  * lu - guid of lu for which view entry is being removed
52187836SJohn.Forte@Sun.COM  * viewEntryIndex - index of view entry to remove
52197836SJohn.Forte@Sun.COM  *
52207836SJohn.Forte@Sun.COM  */
52217836SJohn.Forte@Sun.COM int
52227836SJohn.Forte@Sun.COM stmfRemoveViewEntry(stmfGuid *lu, uint32_t viewEntryIndex)
52237836SJohn.Forte@Sun.COM {
52247836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
52257836SJohn.Forte@Sun.COM 	int fd;
52267836SJohn.Forte@Sun.COM 	int ioctlRet;
52277836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
52287836SJohn.Forte@Sun.COM 	stmf_view_op_entry_t ioctlViewEntry;
52297836SJohn.Forte@Sun.COM 
52307836SJohn.Forte@Sun.COM 	if (lu == NULL) {
52317836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
52327836SJohn.Forte@Sun.COM 	}
52337836SJohn.Forte@Sun.COM 
52347836SJohn.Forte@Sun.COM 	/* call init */
52357836SJohn.Forte@Sun.COM 	ret = initializeConfig();
52367836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
52377836SJohn.Forte@Sun.COM 		return (ret);
52387836SJohn.Forte@Sun.COM 	}
52397836SJohn.Forte@Sun.COM 
52407836SJohn.Forte@Sun.COM 	/*
52417836SJohn.Forte@Sun.COM 	 * Open control node for stmf
52427836SJohn.Forte@Sun.COM 	 */
52437836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
52447836SJohn.Forte@Sun.COM 		return (ret);
52457836SJohn.Forte@Sun.COM 
52467836SJohn.Forte@Sun.COM 	bzero(&ioctlViewEntry, sizeof (ioctlViewEntry));
52477836SJohn.Forte@Sun.COM 	ioctlViewEntry.ve_ndx_valid = B_TRUE;
52487836SJohn.Forte@Sun.COM 	ioctlViewEntry.ve_ndx = viewEntryIndex;
52497836SJohn.Forte@Sun.COM 	bcopy(lu, &ioctlViewEntry.ve_guid, sizeof (stmfGuid));
52507836SJohn.Forte@Sun.COM 
52517836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
52527836SJohn.Forte@Sun.COM 	/*
52537836SJohn.Forte@Sun.COM 	 * Issue ioctl to add to the view entry
52547836SJohn.Forte@Sun.COM 	 */
52557836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
52567836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry);
52577836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry;
52587836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_REMOVE_VIEW_ENTRY, &stmfIoctl);
52597836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
52607836SJohn.Forte@Sun.COM 		switch (errno) {
52617836SJohn.Forte@Sun.COM 			case EBUSY:
52627836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
52637836SJohn.Forte@Sun.COM 				break;
5264*9585STim.Szeto@Sun.COM 			case EPERM:
5265*9585STim.Szeto@Sun.COM 				ret = STMF_ERROR_PERM;
5266*9585STim.Szeto@Sun.COM 				break;
52677836SJohn.Forte@Sun.COM 			case EACCES:
52687836SJohn.Forte@Sun.COM 				switch (stmfIoctl.stmf_error) {
52697836SJohn.Forte@Sun.COM 					case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
52707836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_CONFIG_NONE;
52717836SJohn.Forte@Sun.COM 						break;
52727836SJohn.Forte@Sun.COM 					default:
52737836SJohn.Forte@Sun.COM 						ret = STMF_ERROR_PERM;
52747836SJohn.Forte@Sun.COM 						break;
52757836SJohn.Forte@Sun.COM 				}
52767836SJohn.Forte@Sun.COM 				break;
52777836SJohn.Forte@Sun.COM 			case ENODEV:
52787836SJohn.Forte@Sun.COM 			case ENOENT:
52797836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_NOT_FOUND;
52807836SJohn.Forte@Sun.COM 				break;
52817836SJohn.Forte@Sun.COM 			default:
52827836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
52837836SJohn.Forte@Sun.COM 				    "stmfRemoveViewEntry:ioctl errno(%d)",
52847836SJohn.Forte@Sun.COM 				    errno);
52857836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
52867836SJohn.Forte@Sun.COM 				break;
52877836SJohn.Forte@Sun.COM 		}
52887836SJohn.Forte@Sun.COM 		goto done;
52897836SJohn.Forte@Sun.COM 	}
52907836SJohn.Forte@Sun.COM 
5291*9585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
5292*9585STim.Szeto@Sun.COM 		goto done;
5293*9585STim.Szeto@Sun.COM 	}
5294*9585STim.Szeto@Sun.COM 
52957836SJohn.Forte@Sun.COM 	ret = psRemoveViewEntry(lu, viewEntryIndex);
52967836SJohn.Forte@Sun.COM 	switch (ret) {
52977836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
52987836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
52997836SJohn.Forte@Sun.COM 			break;
53007836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_NOT_FOUND:
53017836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_NOT_FOUND;
53027836SJohn.Forte@Sun.COM 			break;
53037836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
53047836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
53057836SJohn.Forte@Sun.COM 			break;
53067836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
53077836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
53087836SJohn.Forte@Sun.COM 			break;
53097836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
53107836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
53117836SJohn.Forte@Sun.COM 			break;
53127836SJohn.Forte@Sun.COM 		default:
53137836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
53147836SJohn.Forte@Sun.COM 			    "stmfRemoveViewEntry" "psRemoveViewEntry:error(%d)",
53157836SJohn.Forte@Sun.COM 			    ret);
53167836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
53177836SJohn.Forte@Sun.COM 			break;
53187836SJohn.Forte@Sun.COM 	}
53197836SJohn.Forte@Sun.COM 
53207836SJohn.Forte@Sun.COM done:
53217836SJohn.Forte@Sun.COM 	(void) close(fd);
53227836SJohn.Forte@Sun.COM 	return (ret);
53237836SJohn.Forte@Sun.COM }
53247836SJohn.Forte@Sun.COM 
53257836SJohn.Forte@Sun.COM /*
53267836SJohn.Forte@Sun.COM  * stmfSetProviderData
53277836SJohn.Forte@Sun.COM  *
53287836SJohn.Forte@Sun.COM  * Purpose: set the provider data
53297836SJohn.Forte@Sun.COM  *
53307836SJohn.Forte@Sun.COM  * providerName - unique name of provider
53317836SJohn.Forte@Sun.COM  * nvl - nvlist to set
53327836SJohn.Forte@Sun.COM  * providerType - type of provider for which to set data
53337836SJohn.Forte@Sun.COM  *		STMF_LU_PROVIDER_TYPE
53347836SJohn.Forte@Sun.COM  *		STMF_PORT_PROVIDER_TYPE
53357836SJohn.Forte@Sun.COM  */
53367836SJohn.Forte@Sun.COM int
53377836SJohn.Forte@Sun.COM stmfSetProviderData(char *providerName, nvlist_t *nvl, int providerType)
53387836SJohn.Forte@Sun.COM {
53397836SJohn.Forte@Sun.COM 	return (stmfSetProviderDataProt(providerName, nvl, providerType,
53407836SJohn.Forte@Sun.COM 	    NULL));
53417836SJohn.Forte@Sun.COM }
53427836SJohn.Forte@Sun.COM 
53437836SJohn.Forte@Sun.COM /*
53447836SJohn.Forte@Sun.COM  * stmfSetProviderDataProt
53457836SJohn.Forte@Sun.COM  *
53467836SJohn.Forte@Sun.COM  * Purpose: set the provider data
53477836SJohn.Forte@Sun.COM  *
53487836SJohn.Forte@Sun.COM  * providerName - unique name of provider
53497836SJohn.Forte@Sun.COM  * nvl - nvlist to set
53507836SJohn.Forte@Sun.COM  * providerType - type of provider for which to set data
53517836SJohn.Forte@Sun.COM  *		STMF_LU_PROVIDER_TYPE
53527836SJohn.Forte@Sun.COM  *		STMF_PORT_PROVIDER_TYPE
53537836SJohn.Forte@Sun.COM  * setToken - Stale data token returned in the stmfGetProviderDataProt()
53547836SJohn.Forte@Sun.COM  *	      call or NULL.
53557836SJohn.Forte@Sun.COM  */
53567836SJohn.Forte@Sun.COM int
53577836SJohn.Forte@Sun.COM stmfSetProviderDataProt(char *providerName, nvlist_t *nvl, int providerType,
53587836SJohn.Forte@Sun.COM     uint64_t *setToken)
53597836SJohn.Forte@Sun.COM {
53607836SJohn.Forte@Sun.COM 	int ret;
53617836SJohn.Forte@Sun.COM 	int fd;
53627836SJohn.Forte@Sun.COM 
53637836SJohn.Forte@Sun.COM 	if (providerName == NULL || nvl == NULL) {
53647836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
53657836SJohn.Forte@Sun.COM 	}
53667836SJohn.Forte@Sun.COM 
53677836SJohn.Forte@Sun.COM 	if (providerType != STMF_LU_PROVIDER_TYPE &&
53687836SJohn.Forte@Sun.COM 	    providerType != STMF_PORT_PROVIDER_TYPE) {
53697836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
53707836SJohn.Forte@Sun.COM 	}
53717836SJohn.Forte@Sun.COM 
53727836SJohn.Forte@Sun.COM 	/* call init */
53737836SJohn.Forte@Sun.COM 	ret = initializeConfig();
53747836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
53757836SJohn.Forte@Sun.COM 		return (ret);
53767836SJohn.Forte@Sun.COM 	}
53777836SJohn.Forte@Sun.COM 
53787836SJohn.Forte@Sun.COM 	/*
53797836SJohn.Forte@Sun.COM 	 * Open control node for stmf
53807836SJohn.Forte@Sun.COM 	 */
53817836SJohn.Forte@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
53827836SJohn.Forte@Sun.COM 		return (ret);
53837836SJohn.Forte@Sun.COM 
5384*9585STim.Szeto@Sun.COM 	ret = setProviderData(fd, providerName, nvl, providerType, setToken);
53857836SJohn.Forte@Sun.COM 
53867836SJohn.Forte@Sun.COM 	(void) close(fd);
53877836SJohn.Forte@Sun.COM 
53887836SJohn.Forte@Sun.COM 	if (ret != STMF_STATUS_SUCCESS) {
53897836SJohn.Forte@Sun.COM 		goto done;
53907836SJohn.Forte@Sun.COM 	}
53917836SJohn.Forte@Sun.COM 
5392*9585STim.Szeto@Sun.COM 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
5393*9585STim.Szeto@Sun.COM 		goto done;
5394*9585STim.Szeto@Sun.COM 	}
5395*9585STim.Szeto@Sun.COM 
53967836SJohn.Forte@Sun.COM 	/* setting driver provider data successful. Now persist it */
5397*9585STim.Szeto@Sun.COM 	ret = psSetProviderData(providerName, nvl, providerType, NULL);
53987836SJohn.Forte@Sun.COM 	switch (ret) {
53997836SJohn.Forte@Sun.COM 		case STMF_PS_SUCCESS:
54007836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_SUCCESS;
54017836SJohn.Forte@Sun.COM 			break;
54027836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_EXISTS:
54037836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_EXISTS;
54047836SJohn.Forte@Sun.COM 			break;
54057836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_BUSY:
54067836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_BUSY;
54077836SJohn.Forte@Sun.COM 			break;
54087836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
54097836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
54107836SJohn.Forte@Sun.COM 			break;
54117836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_VERSION_MISMATCH:
54127836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
54137836SJohn.Forte@Sun.COM 			break;
54147836SJohn.Forte@Sun.COM 		case STMF_PS_ERROR_PROV_DATA_STALE:
54157836SJohn.Forte@Sun.COM 			ret = STMF_ERROR_PROV_DATA_STALE;
54167836SJohn.Forte@Sun.COM 			break;
54177836SJohn.Forte@Sun.COM 		default:
54187836SJohn.Forte@Sun.COM 			syslog(LOG_DEBUG,
54197836SJohn.Forte@Sun.COM 			    "stmfSetProviderData"
54207836SJohn.Forte@Sun.COM 			    "psSetProviderData:error(%d)", ret);
54217836SJohn.Forte@Sun.COM 			ret = STMF_STATUS_ERROR;
54227836SJohn.Forte@Sun.COM 			break;
54237836SJohn.Forte@Sun.COM 	}
54247836SJohn.Forte@Sun.COM 
54257836SJohn.Forte@Sun.COM done:
54267836SJohn.Forte@Sun.COM 	return (ret);
54277836SJohn.Forte@Sun.COM }
54287836SJohn.Forte@Sun.COM 
54297836SJohn.Forte@Sun.COM /*
5430*9585STim.Szeto@Sun.COM  * getProviderData
5431*9585STim.Szeto@Sun.COM  *
5432*9585STim.Szeto@Sun.COM  * Purpose: set the provider data from stmf
5433*9585STim.Szeto@Sun.COM  *
5434*9585STim.Szeto@Sun.COM  * providerName - unique name of provider
5435*9585STim.Szeto@Sun.COM  * nvl - nvlist to load/retrieve
5436*9585STim.Szeto@Sun.COM  * providerType - logical unit or port provider
5437*9585STim.Szeto@Sun.COM  * setToken - returned stale data token
5438*9585STim.Szeto@Sun.COM  */
5439*9585STim.Szeto@Sun.COM int
5440*9585STim.Szeto@Sun.COM getProviderData(char *providerName, nvlist_t **nvl, int providerType,
5441*9585STim.Szeto@Sun.COM     uint64_t *setToken)
5442*9585STim.Szeto@Sun.COM {
5443*9585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
5444*9585STim.Szeto@Sun.COM 	int fd;
5445*9585STim.Szeto@Sun.COM 	int ioctlRet;
5446*9585STim.Szeto@Sun.COM 	size_t nvlistSize = ALLOC_PP_DATA_SIZE;
5447*9585STim.Szeto@Sun.COM 	int retryCnt = 0;
5448*9585STim.Szeto@Sun.COM 	int retryCntMax = MAX_PROVIDER_RETRY;
5449*9585STim.Szeto@Sun.COM 	stmf_ppioctl_data_t ppi = {0}, *ppi_out = NULL;
5450*9585STim.Szeto@Sun.COM 	boolean_t retry = B_TRUE;
5451*9585STim.Szeto@Sun.COM 	stmf_iocdata_t stmfIoctl;
5452*9585STim.Szeto@Sun.COM 
5453*9585STim.Szeto@Sun.COM 	if (providerName == NULL) {
5454*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
5455*9585STim.Szeto@Sun.COM 	}
5456*9585STim.Szeto@Sun.COM 
5457*9585STim.Szeto@Sun.COM 	/*
5458*9585STim.Szeto@Sun.COM 	 * Open control node for stmf
5459*9585STim.Szeto@Sun.COM 	 */
5460*9585STim.Szeto@Sun.COM 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
5461*9585STim.Szeto@Sun.COM 		return (ret);
5462*9585STim.Szeto@Sun.COM 
5463*9585STim.Szeto@Sun.COM 	/* set provider name and provider type */
5464*9585STim.Szeto@Sun.COM 	if (strlcpy(ppi.ppi_name, providerName,
5465*9585STim.Szeto@Sun.COM 	    sizeof (ppi.ppi_name)) >=
5466*9585STim.Szeto@Sun.COM 	    sizeof (ppi.ppi_name)) {
5467*9585STim.Szeto@Sun.COM 		ret = STMF_ERROR_INVALID_ARG;
5468*9585STim.Szeto@Sun.COM 		goto done;
5469*9585STim.Szeto@Sun.COM 	}
5470*9585STim.Szeto@Sun.COM 	switch (providerType) {
5471*9585STim.Szeto@Sun.COM 		case STMF_LU_PROVIDER_TYPE:
5472*9585STim.Szeto@Sun.COM 			ppi.ppi_lu_provider = 1;
5473*9585STim.Szeto@Sun.COM 			break;
5474*9585STim.Szeto@Sun.COM 		case STMF_PORT_PROVIDER_TYPE:
5475*9585STim.Szeto@Sun.COM 			ppi.ppi_port_provider = 1;
5476*9585STim.Szeto@Sun.COM 			break;
5477*9585STim.Szeto@Sun.COM 		default:
5478*9585STim.Szeto@Sun.COM 			ret = STMF_ERROR_INVALID_ARG;
5479*9585STim.Szeto@Sun.COM 			goto done;
5480*9585STim.Szeto@Sun.COM 	}
5481*9585STim.Szeto@Sun.COM 
5482*9585STim.Szeto@Sun.COM 	do {
5483*9585STim.Szeto@Sun.COM 		/* allocate memory for ioctl */
5484*9585STim.Szeto@Sun.COM 		ppi_out = (stmf_ppioctl_data_t *)calloc(1, nvlistSize +
5485*9585STim.Szeto@Sun.COM 		    sizeof (stmf_ppioctl_data_t));
5486*9585STim.Szeto@Sun.COM 		if (ppi_out == NULL) {
5487*9585STim.Szeto@Sun.COM 			ret = STMF_ERROR_NOMEM;
5488*9585STim.Szeto@Sun.COM 			goto done;
5489*9585STim.Szeto@Sun.COM 
5490*9585STim.Szeto@Sun.COM 		}
5491*9585STim.Szeto@Sun.COM 
5492*9585STim.Szeto@Sun.COM 		/* set the size of the ioctl data to allocated buffer */
5493*9585STim.Szeto@Sun.COM 		ppi.ppi_data_size = nvlistSize;
5494*9585STim.Szeto@Sun.COM 
5495*9585STim.Szeto@Sun.COM 		bzero(&stmfIoctl, sizeof (stmfIoctl));
5496*9585STim.Szeto@Sun.COM 
5497*9585STim.Szeto@Sun.COM 		stmfIoctl.stmf_version = STMF_VERSION_1;
5498*9585STim.Szeto@Sun.COM 		stmfIoctl.stmf_ibuf_size = sizeof (stmf_ppioctl_data_t);
5499*9585STim.Szeto@Sun.COM 		stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ppi;
5500*9585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf_size = sizeof (stmf_ppioctl_data_t) +
5501*9585STim.Szeto@Sun.COM 		    nvlistSize;
5502*9585STim.Szeto@Sun.COM 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)ppi_out;
5503*9585STim.Szeto@Sun.COM 		ioctlRet = ioctl(fd, STMF_IOCTL_GET_PP_DATA, &stmfIoctl);
5504*9585STim.Szeto@Sun.COM 		if (ioctlRet != 0) {
5505*9585STim.Szeto@Sun.COM 			switch (errno) {
5506*9585STim.Szeto@Sun.COM 				case EBUSY:
5507*9585STim.Szeto@Sun.COM 					ret = STMF_ERROR_BUSY;
5508*9585STim.Szeto@Sun.COM 					break;
5509*9585STim.Szeto@Sun.COM 				case EPERM:
5510*9585STim.Szeto@Sun.COM 				case EACCES:
5511*9585STim.Szeto@Sun.COM 					ret = STMF_ERROR_PERM;
5512*9585STim.Szeto@Sun.COM 					break;
5513*9585STim.Szeto@Sun.COM 				case EINVAL:
5514*9585STim.Szeto@Sun.COM 					if (stmfIoctl.stmf_error ==
5515*9585STim.Szeto@Sun.COM 					    STMF_IOCERR_INSUFFICIENT_BUF) {
5516*9585STim.Szeto@Sun.COM 						nvlistSize =
5517*9585STim.Szeto@Sun.COM 						    ppi_out->ppi_data_size;
5518*9585STim.Szeto@Sun.COM 						free(ppi_out);
5519*9585STim.Szeto@Sun.COM 						ppi_out = NULL;
5520*9585STim.Szeto@Sun.COM 						if (retryCnt++ > retryCntMax) {
5521*9585STim.Szeto@Sun.COM 							retry = B_FALSE;
5522*9585STim.Szeto@Sun.COM 							ret = STMF_ERROR_BUSY;
5523*9585STim.Szeto@Sun.COM 						} else {
5524*9585STim.Szeto@Sun.COM 							ret =
5525*9585STim.Szeto@Sun.COM 							    STMF_STATUS_SUCCESS;
5526*9585STim.Szeto@Sun.COM 						}
5527*9585STim.Szeto@Sun.COM 					} else {
5528*9585STim.Szeto@Sun.COM 						syslog(LOG_DEBUG,
5529*9585STim.Szeto@Sun.COM 						    "getProviderData:ioctl"
5530*9585STim.Szeto@Sun.COM 						    "unable to retrieve "
5531*9585STim.Szeto@Sun.COM 						    "nvlist");
5532*9585STim.Szeto@Sun.COM 						ret = STMF_STATUS_ERROR;
5533*9585STim.Szeto@Sun.COM 					}
5534*9585STim.Szeto@Sun.COM 					break;
5535*9585STim.Szeto@Sun.COM 				case ENOENT:
5536*9585STim.Szeto@Sun.COM 					ret = STMF_ERROR_NOT_FOUND;
5537*9585STim.Szeto@Sun.COM 					break;
5538*9585STim.Szeto@Sun.COM 				default:
5539*9585STim.Szeto@Sun.COM 					syslog(LOG_DEBUG,
5540*9585STim.Szeto@Sun.COM 					    "getProviderData:ioctl errno(%d)",
5541*9585STim.Szeto@Sun.COM 					    errno);
5542*9585STim.Szeto@Sun.COM 					ret = STMF_STATUS_ERROR;
5543*9585STim.Szeto@Sun.COM 					break;
5544*9585STim.Szeto@Sun.COM 			}
5545*9585STim.Szeto@Sun.COM 			if (ret != STMF_STATUS_SUCCESS)
5546*9585STim.Szeto@Sun.COM 				goto done;
5547*9585STim.Szeto@Sun.COM 		}
5548*9585STim.Szeto@Sun.COM 	} while (retry && stmfIoctl.stmf_error == STMF_IOCERR_INSUFFICIENT_BUF);
5549*9585STim.Szeto@Sun.COM 
5550*9585STim.Szeto@Sun.COM 	if ((ret = nvlist_unpack((char *)ppi_out->ppi_data,
5551*9585STim.Szeto@Sun.COM 	    ppi_out->ppi_data_size, nvl, 0)) != 0) {
5552*9585STim.Szeto@Sun.COM 		ret = STMF_STATUS_ERROR;
5553*9585STim.Szeto@Sun.COM 		goto done;
5554*9585STim.Szeto@Sun.COM 	}
5555*9585STim.Szeto@Sun.COM 
5556*9585STim.Szeto@Sun.COM 	/* caller has asked for new token */
5557*9585STim.Szeto@Sun.COM 	if (setToken) {
5558*9585STim.Szeto@Sun.COM 		*setToken = ppi_out->ppi_token;
5559*9585STim.Szeto@Sun.COM 	}
5560*9585STim.Szeto@Sun.COM done:
5561*9585STim.Szeto@Sun.COM 	free(ppi_out);
5562*9585STim.Szeto@Sun.COM 	(void) close(fd);
5563*9585STim.Szeto@Sun.COM 	return (ret);
5564*9585STim.Szeto@Sun.COM }
5565*9585STim.Szeto@Sun.COM 
5566*9585STim.Szeto@Sun.COM /*
55677836SJohn.Forte@Sun.COM  * setProviderData
55687836SJohn.Forte@Sun.COM  *
5569*9585STim.Szeto@Sun.COM  * Purpose: set the provider data in stmf
55707836SJohn.Forte@Sun.COM  *
55717836SJohn.Forte@Sun.COM  * providerName - unique name of provider
55727836SJohn.Forte@Sun.COM  * nvl - nvlist to set
55737836SJohn.Forte@Sun.COM  * providerType - logical unit or port provider
5574*9585STim.Szeto@Sun.COM  * setToken - stale data token to check if not NULL
55757836SJohn.Forte@Sun.COM  */
55767836SJohn.Forte@Sun.COM static int
5577*9585STim.Szeto@Sun.COM setProviderData(int fd, char *providerName, nvlist_t *nvl, int providerType,
5578*9585STim.Szeto@Sun.COM     uint64_t *setToken)
55797836SJohn.Forte@Sun.COM {
55807836SJohn.Forte@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
55817836SJohn.Forte@Sun.COM 	int ioctlRet;
55827836SJohn.Forte@Sun.COM 	size_t nvlistEncodedSize;
55837836SJohn.Forte@Sun.COM 	stmf_ppioctl_data_t *ppi = NULL;
5584*9585STim.Szeto@Sun.COM 	uint64_t outToken;
55857836SJohn.Forte@Sun.COM 	char *allocatedNvBuffer;
55867836SJohn.Forte@Sun.COM 	stmf_iocdata_t stmfIoctl;
55877836SJohn.Forte@Sun.COM 
55887836SJohn.Forte@Sun.COM 	if (providerName == NULL) {
55897836SJohn.Forte@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
55907836SJohn.Forte@Sun.COM 	}
55917836SJohn.Forte@Sun.COM 
55927836SJohn.Forte@Sun.COM 	/* get size of encoded nvlist */
55937836SJohn.Forte@Sun.COM 	if (nvlist_size(nvl, &nvlistEncodedSize, NV_ENCODE_XDR) != 0) {
55947836SJohn.Forte@Sun.COM 		return (STMF_STATUS_ERROR);
55957836SJohn.Forte@Sun.COM 	}
55967836SJohn.Forte@Sun.COM 
55977836SJohn.Forte@Sun.COM 	/* allocate memory for ioctl */
55987836SJohn.Forte@Sun.COM 	ppi = (stmf_ppioctl_data_t *)calloc(1, nvlistEncodedSize +
55997836SJohn.Forte@Sun.COM 	    sizeof (stmf_ppioctl_data_t));
56007836SJohn.Forte@Sun.COM 	if (ppi == NULL) {
56017836SJohn.Forte@Sun.COM 		return (STMF_ERROR_NOMEM);
56027836SJohn.Forte@Sun.COM 	}
56037836SJohn.Forte@Sun.COM 
5604*9585STim.Szeto@Sun.COM 	if (setToken) {
5605*9585STim.Szeto@Sun.COM 		ppi->ppi_token_valid = 1;
5606*9585STim.Szeto@Sun.COM 		ppi->ppi_token = *setToken;
5607*9585STim.Szeto@Sun.COM 	}
5608*9585STim.Szeto@Sun.COM 
56097836SJohn.Forte@Sun.COM 	allocatedNvBuffer = (char *)&ppi->ppi_data;
56107836SJohn.Forte@Sun.COM 	if (nvlist_pack(nvl, &allocatedNvBuffer, &nvlistEncodedSize,
56117836SJohn.Forte@Sun.COM 	    NV_ENCODE_XDR, 0) != 0) {
56127836SJohn.Forte@Sun.COM 		return (STMF_STATUS_ERROR);
56137836SJohn.Forte@Sun.COM 	}
56147836SJohn.Forte@Sun.COM 
56157836SJohn.Forte@Sun.COM 	/* set provider name and provider type */
56167836SJohn.Forte@Sun.COM 	(void) strncpy(ppi->ppi_name, providerName, sizeof (ppi->ppi_name));
56177836SJohn.Forte@Sun.COM 	switch (providerType) {
56187836SJohn.Forte@Sun.COM 		case STMF_LU_PROVIDER_TYPE:
56197836SJohn.Forte@Sun.COM 			ppi->ppi_lu_provider = 1;
56207836SJohn.Forte@Sun.COM 			break;
56217836SJohn.Forte@Sun.COM 		case STMF_PORT_PROVIDER_TYPE:
56227836SJohn.Forte@Sun.COM 			ppi->ppi_port_provider = 1;
56237836SJohn.Forte@Sun.COM 			break;
56247836SJohn.Forte@Sun.COM 		default:
56257836SJohn.Forte@Sun.COM 			return (STMF_ERROR_INVALID_ARG);
56267836SJohn.Forte@Sun.COM 	}
56277836SJohn.Forte@Sun.COM 
56287836SJohn.Forte@Sun.COM 	/* set the size of the ioctl data to packed data size */
56297836SJohn.Forte@Sun.COM 	ppi->ppi_data_size = nvlistEncodedSize;
56307836SJohn.Forte@Sun.COM 
56317836SJohn.Forte@Sun.COM 	bzero(&stmfIoctl, sizeof (stmfIoctl));
56327836SJohn.Forte@Sun.COM 
56337836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_version = STMF_VERSION_1;
56347836SJohn.Forte@Sun.COM 	/*
56357836SJohn.Forte@Sun.COM 	 * Subtracting 8 from the size as that is the size of the last member
56367836SJohn.Forte@Sun.COM 	 * of the structure where the packed data resides
56377836SJohn.Forte@Sun.COM 	 */
56387836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf_size = nvlistEncodedSize +
56397836SJohn.Forte@Sun.COM 	    sizeof (stmf_ppioctl_data_t) - 8;
56407836SJohn.Forte@Sun.COM 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)ppi;
5641*9585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf_size = sizeof (uint64_t);
5642*9585STim.Szeto@Sun.COM 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&outToken;
56437836SJohn.Forte@Sun.COM 	ioctlRet = ioctl(fd, STMF_IOCTL_LOAD_PP_DATA, &stmfIoctl);
56447836SJohn.Forte@Sun.COM 	if (ioctlRet != 0) {
56457836SJohn.Forte@Sun.COM 		switch (errno) {
56467836SJohn.Forte@Sun.COM 			case EBUSY:
56477836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_BUSY;
56487836SJohn.Forte@Sun.COM 				break;
5649*9585STim.Szeto@Sun.COM 			case EPERM:
56507836SJohn.Forte@Sun.COM 			case EACCES:
56517836SJohn.Forte@Sun.COM 				ret = STMF_ERROR_PERM;
56527836SJohn.Forte@Sun.COM 				break;
5653*9585STim.Szeto@Sun.COM 			case EINVAL:
5654*9585STim.Szeto@Sun.COM 				if (stmfIoctl.stmf_error ==
5655*9585STim.Szeto@Sun.COM 				    STMF_IOCERR_PPD_UPDATED) {
5656*9585STim.Szeto@Sun.COM 					ret = STMF_ERROR_PROV_DATA_STALE;
5657*9585STim.Szeto@Sun.COM 				} else {
5658*9585STim.Szeto@Sun.COM 					ret = STMF_STATUS_ERROR;
5659*9585STim.Szeto@Sun.COM 				}
5660*9585STim.Szeto@Sun.COM 				break;
56617836SJohn.Forte@Sun.COM 			default:
56627836SJohn.Forte@Sun.COM 				syslog(LOG_DEBUG,
56637836SJohn.Forte@Sun.COM 				    "setProviderData:ioctl errno(%d)", errno);
56647836SJohn.Forte@Sun.COM 				ret = STMF_STATUS_ERROR;
56657836SJohn.Forte@Sun.COM 				break;
56667836SJohn.Forte@Sun.COM 		}
56677836SJohn.Forte@Sun.COM 		if (ret != STMF_STATUS_SUCCESS)
56687836SJohn.Forte@Sun.COM 			goto done;
56697836SJohn.Forte@Sun.COM 	}
56707836SJohn.Forte@Sun.COM 
5671*9585STim.Szeto@Sun.COM 	/* caller has asked for new token */
5672*9585STim.Szeto@Sun.COM 	if (setToken) {
5673*9585STim.Szeto@Sun.COM 		*setToken = outToken;
5674*9585STim.Szeto@Sun.COM 	}
56757836SJohn.Forte@Sun.COM done:
56767836SJohn.Forte@Sun.COM 	free(ppi);
56777836SJohn.Forte@Sun.COM 	return (ret);
56787836SJohn.Forte@Sun.COM }
5679*9585STim.Szeto@Sun.COM 
5680*9585STim.Szeto@Sun.COM /*
5681*9585STim.Szeto@Sun.COM  * set the persistence method in the library only or library and service
5682*9585STim.Szeto@Sun.COM  */
5683*9585STim.Szeto@Sun.COM int
5684*9585STim.Szeto@Sun.COM stmfSetPersistMethod(uint8_t persistType, boolean_t serviceSet)
5685*9585STim.Szeto@Sun.COM {
5686*9585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
5687*9585STim.Szeto@Sun.COM 	int oldPersist;
5688*9585STim.Szeto@Sun.COM 
5689*9585STim.Szeto@Sun.COM 	(void) pthread_mutex_lock(&persistenceTypeLock);
5690*9585STim.Szeto@Sun.COM 	oldPersist = iPersistType;
5691*9585STim.Szeto@Sun.COM 	if (persistType == STMF_PERSIST_NONE ||
5692*9585STim.Szeto@Sun.COM 	    persistType == STMF_PERSIST_SMF) {
5693*9585STim.Szeto@Sun.COM 		iLibSetPersist = B_TRUE;
5694*9585STim.Szeto@Sun.COM 		iPersistType = persistType;
5695*9585STim.Szeto@Sun.COM 	} else {
5696*9585STim.Szeto@Sun.COM 		(void) pthread_mutex_unlock(&persistenceTypeLock);
5697*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
5698*9585STim.Szeto@Sun.COM 	}
5699*9585STim.Szeto@Sun.COM 	/* Is this for this library open or in SMF */
5700*9585STim.Szeto@Sun.COM 	if (serviceSet == B_TRUE) {
5701*9585STim.Szeto@Sun.COM 		ret = psSetServicePersist(persistType);
5702*9585STim.Szeto@Sun.COM 		if (ret != STMF_PS_SUCCESS) {
5703*9585STim.Szeto@Sun.COM 			ret = STMF_ERROR_PERSIST_TYPE;
5704*9585STim.Szeto@Sun.COM 			/* Set to old value */
5705*9585STim.Szeto@Sun.COM 			iPersistType = oldPersist;
5706*9585STim.Szeto@Sun.COM 		}
5707*9585STim.Szeto@Sun.COM 	}
5708*9585STim.Szeto@Sun.COM 	(void) pthread_mutex_unlock(&persistenceTypeLock);
5709*9585STim.Szeto@Sun.COM 
5710*9585STim.Szeto@Sun.COM 	return (ret);
5711*9585STim.Szeto@Sun.COM }
5712*9585STim.Szeto@Sun.COM 
5713*9585STim.Szeto@Sun.COM /*
5714*9585STim.Szeto@Sun.COM  * Only returns internal state for persist. If unset, goes to ps. If that
5715*9585STim.Szeto@Sun.COM  * fails, returns default setting
5716*9585STim.Szeto@Sun.COM  */
5717*9585STim.Szeto@Sun.COM static uint8_t
5718*9585STim.Szeto@Sun.COM iGetPersistMethod()
5719*9585STim.Szeto@Sun.COM {
5720*9585STim.Szeto@Sun.COM 
5721*9585STim.Szeto@Sun.COM 	uint8_t persistType = 0;
5722*9585STim.Szeto@Sun.COM 
5723*9585STim.Szeto@Sun.COM 	(void) pthread_mutex_lock(&persistenceTypeLock);
5724*9585STim.Szeto@Sun.COM 	if (iLibSetPersist) {
5725*9585STim.Szeto@Sun.COM 		persistType = iPersistType;
5726*9585STim.Szeto@Sun.COM 	} else {
5727*9585STim.Szeto@Sun.COM 		int ret;
5728*9585STim.Szeto@Sun.COM 		ret = psGetServicePersist(&persistType);
5729*9585STim.Szeto@Sun.COM 		if (ret != STMF_PS_SUCCESS) {
5730*9585STim.Szeto@Sun.COM 			/* set to default */
5731*9585STim.Szeto@Sun.COM 			persistType = STMF_DEFAULT_PERSIST;
5732*9585STim.Szeto@Sun.COM 		}
5733*9585STim.Szeto@Sun.COM 	}
5734*9585STim.Szeto@Sun.COM 	(void) pthread_mutex_unlock(&persistenceTypeLock);
5735*9585STim.Szeto@Sun.COM 	return (persistType);
5736*9585STim.Szeto@Sun.COM }
5737*9585STim.Szeto@Sun.COM 
5738*9585STim.Szeto@Sun.COM /*
5739*9585STim.Szeto@Sun.COM  * Returns either library state or persistent config state depending on
5740*9585STim.Szeto@Sun.COM  * serviceState
5741*9585STim.Szeto@Sun.COM  */
5742*9585STim.Szeto@Sun.COM int
5743*9585STim.Szeto@Sun.COM stmfGetPersistMethod(uint8_t *persistType, boolean_t serviceState)
5744*9585STim.Szeto@Sun.COM {
5745*9585STim.Szeto@Sun.COM 	int ret = STMF_STATUS_SUCCESS;
5746*9585STim.Szeto@Sun.COM 
5747*9585STim.Szeto@Sun.COM 	if (persistType == NULL) {
5748*9585STim.Szeto@Sun.COM 		return (STMF_ERROR_INVALID_ARG);
5749*9585STim.Szeto@Sun.COM 	}
5750*9585STim.Szeto@Sun.COM 	if (serviceState) {
5751*9585STim.Szeto@Sun.COM 		ret = psGetServicePersist(persistType);
5752*9585STim.Szeto@Sun.COM 		if (ret != STMF_PS_SUCCESS) {
5753*9585STim.Szeto@Sun.COM 			ret = STMF_ERROR_PERSIST_TYPE;
5754*9585STim.Szeto@Sun.COM 		}
5755*9585STim.Szeto@Sun.COM 	} else {
5756*9585STim.Szeto@Sun.COM 		(void) pthread_mutex_lock(&persistenceTypeLock);
5757*9585STim.Szeto@Sun.COM 		if (iLibSetPersist) {
5758*9585STim.Szeto@Sun.COM 			*persistType = iPersistType;
5759*9585STim.Szeto@Sun.COM 		} else {
5760*9585STim.Szeto@Sun.COM 			*persistType = STMF_DEFAULT_PERSIST;
5761*9585STim.Szeto@Sun.COM 		}
5762*9585STim.Szeto@Sun.COM 		(void) pthread_mutex_unlock(&persistenceTypeLock);
5763*9585STim.Szeto@Sun.COM 	}
5764*9585STim.Szeto@Sun.COM 
5765*9585STim.Szeto@Sun.COM 	return (ret);
5766*9585STim.Szeto@Sun.COM }
5767