xref: /illumos-gate/usr/src/lib/libstmf/common/stmf.c (revision 45039663)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <wchar.h>
29 #include <strings.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 #include <unistd.h>
34 #include <libintl.h>
35 #include <errno.h>
36 #include <string.h>
37 #include <assert.h>
38 #include <libnvpair.h>
39 #include <pthread.h>
40 #include <syslog.h>
41 #include <libstmf.h>
42 #include <netinet/in.h>
43 #include <inttypes.h>
44 #include <store.h>
45 #include <locale.h>
46 #include <math.h>
47 #include <libstmf_impl.h>
48 #include <sys/stmf_ioctl.h>
49 #include <sys/stmf_sbd_ioctl.h>
50 #include <sys/pppt_ioctl.h>
51 
52 #define	STMF_PATH    "/devices/pseudo/stmf@0:admin"
53 #define	SBD_PATH    "/devices/pseudo/stmf_sbd@0:admin"
54 #define	PPPT_PATH    "/devices/pseudo/pppt@0:pppt"
55 
56 #define	EUI "eui."
57 #define	WWN "wwn."
58 #define	IQN "iqn."
59 #define	LU_ASCII_GUID_SIZE 32
60 #define	LU_GUID_SIZE 16
61 #define	OUI_ASCII_SIZE 6
62 #define	OUI_SIZE 3
63 #define	IDENT_LENGTH_BYTE 3
64 
65 /* various initial allocation values */
66 #define	ALLOC_LU		8192
67 #define	ALLOC_TARGET_PORT	2048
68 #define	ALLOC_PROVIDER		64
69 #define	ALLOC_GROUP		2048
70 #define	ALLOC_SESSION		2048
71 #define	ALLOC_VE		256
72 #define	ALLOC_PP_DATA_SIZE	128*1024
73 #define	ALLOC_GRP_MEMBER	256
74 
75 #define	MAX_ISCSI_NAME	223
76 #define	MAX_SERIAL_SIZE 252 + 1
77 #define	MAX_LU_ALIAS_SIZE 256
78 #define	MAX_SBD_PROPS	MAXPATHLEN + MAX_SERIAL_SIZE + MAX_LU_ALIAS_SIZE
79 
80 #define	OPEN_STMF 0
81 #define	OPEN_EXCL_STMF O_EXCL
82 
83 #define	OPEN_SBD 0
84 #define	OPEN_EXCL_SBD O_EXCL
85 
86 #define	OPEN_PPPT 0
87 #define	OPEN_EXCL_PPPT O_EXCL
88 
89 #define	LOGICAL_UNIT_TYPE 0
90 #define	TARGET_TYPE 1
91 #define	STMF_SERVICE_TYPE 2
92 
93 #define	HOST_GROUP   1
94 #define	TARGET_GROUP 2
95 
96 /* set default persistence here */
97 #define	STMF_DEFAULT_PERSIST	STMF_PERSIST_SMF
98 
99 #define	MAX_PROVIDER_RETRY 30
100 
101 static int openStmf(int, int *fd);
102 static int openSbd(int, int *fd);
103 static int openPppt(int, int *fd);
104 static int groupIoctl(int fd, int cmd, stmfGroupName *);
105 static int loadStore(int fd);
106 static int initializeConfig();
107 static int groupMemberIoctl(int fd, int cmd, stmfGroupName *, stmfDevid *);
108 static int guidCompare(const void *, const void *);
109 static int addViewEntryIoctl(int fd, stmfGuid *, stmfViewEntry *);
110 static int loadHostGroups(int fd, stmfGroupList *);
111 static int loadTargetGroups(int fd, stmfGroupList *);
112 static int getStmfState(stmf_state_desc_t *);
113 static int setStmfState(int fd, stmf_state_desc_t *, int);
114 static int setProviderData(int fd, char *, nvlist_t *, int, uint64_t *);
115 static int createDiskResource(luResourceImpl *);
116 static int createDiskLu(diskResource *, stmfGuid *);
117 static int deleteDiskLu(stmfGuid *luGuid);
118 static int getDiskProp(luResourceImpl *, uint32_t, char *, size_t *);
119 static int getDiskAllProps(stmfGuid *luGuid, luResource *hdl);
120 static int loadDiskPropsFromDriver(luResourceImpl *, sbd_lu_props_t *);
121 static int removeGuidFromDiskStore(stmfGuid *);
122 static int addGuidToDiskStore(stmfGuid *, char *);
123 static int persistDiskGuid(stmfGuid *, char *, boolean_t);
124 static int setDiskProp(luResourceImpl *, uint32_t, const char *);
125 static int checkHexUpper(char *);
126 static int strToShift(const char *);
127 static int niceStrToNum(const char *, uint64_t *);
128 static void diskError(uint32_t, int *);
129 static int importDiskLu(char *fname, stmfGuid *);
130 static int modifyDiskLu(diskResource *, stmfGuid *, const char *);
131 static int modifyDiskLuProp(stmfGuid *, const char *, uint32_t, const char *);
132 static int validateModifyDiskProp(uint32_t);
133 static uint8_t iGetPersistMethod();
134 static int groupListIoctl(stmfGroupList **, int);
135 static int iLoadGroupFromPs(stmfGroupList **, int);
136 static int groupMemberListIoctl(stmfGroupName *, stmfGroupProperties **, int);
137 static int getProviderData(char *, nvlist_t **, int, uint64_t *);
138 static int setDiskStandby(stmfGuid *luGuid);
139 static int viewEntryCompare(const void *, const void *);
140 static void deleteNonActiveLus();
141 
142 static pthread_mutex_t persistenceTypeLock = PTHREAD_MUTEX_INITIALIZER;
143 static int iPersistType = 0;
144 /* when B_TRUE, no need to access SMF anymore. Just use iPersistType */
145 static boolean_t iLibSetPersist = B_FALSE;
146 
147 /*
148  * Open for stmf module
149  *
150  * flag - open flag (OPEN_STMF, OPEN_EXCL_STMF)
151  * fd - pointer to integer. On success, contains the stmf file descriptor
152  */
153 static int
154 openStmf(int flag, int *fd)
155 {
156 	int ret = STMF_STATUS_ERROR;
157 
158 	if ((*fd = open(STMF_PATH, O_NDELAY | O_RDONLY | flag)) != -1) {
159 		ret = STMF_STATUS_SUCCESS;
160 	} else {
161 		if (errno == EBUSY) {
162 			ret = STMF_ERROR_BUSY;
163 		} else if (errno == EACCES) {
164 			ret = STMF_ERROR_PERM;
165 		} else {
166 			ret = STMF_STATUS_ERROR;
167 		}
168 		syslog(LOG_DEBUG, "openStmf:open failure:%s:errno(%d)",
169 		    STMF_PATH, errno);
170 	}
171 
172 	return (ret);
173 }
174 
175 /*
176  * Open for sbd module
177  *
178  * flag - open flag (OPEN_SBD, OPEN_EXCL_SBD)
179  * fd - pointer to integer. On success, contains the stmf file descriptor
180  */
181 static int
182 openSbd(int flag, int *fd)
183 {
184 	int ret = STMF_STATUS_ERROR;
185 
186 	if ((*fd = open(SBD_PATH, O_NDELAY | O_RDONLY | flag)) != -1) {
187 		ret = STMF_STATUS_SUCCESS;
188 	} else {
189 		if (errno == EBUSY) {
190 			ret = STMF_ERROR_BUSY;
191 		} else if (errno == EACCES) {
192 			ret = STMF_ERROR_PERM;
193 		} else {
194 			ret = STMF_STATUS_ERROR;
195 		}
196 		syslog(LOG_DEBUG, "openSbd:open failure:%s:errno(%d)",
197 		    SBD_PATH, errno);
198 	}
199 
200 	return (ret);
201 }
202 
203 /*
204  * Open for pppt module
205  *
206  * flag - open flag (OPEN_PPPT, OPEN_EXCL_PPPT)
207  * fd - pointer to integer. On success, contains the stmf file descriptor
208  */
209 static int
210 openPppt(int flag, int *fd)
211 {
212 	int ret = STMF_STATUS_ERROR;
213 
214 	if ((*fd = open(PPPT_PATH, O_RDONLY | flag)) != -1) {
215 		ret = STMF_STATUS_SUCCESS;
216 	} else {
217 		if (errno == EBUSY) {
218 			ret = STMF_ERROR_BUSY;
219 		} else if (errno == EACCES) {
220 			ret = STMF_ERROR_PERM;
221 		} else {
222 			ret = STMF_STATUS_ERROR;
223 		}
224 		syslog(LOG_DEBUG, "openPppt:open failure:%s:errno(%d)",
225 		    PPPT_PATH, errno);
226 	}
227 
228 	return (ret);
229 }
230 
231 /*
232  * initializeConfig
233  *
234  * This routine should be called before any ioctl requiring initialization
235  * which is basically everything except stmfGetState(), setStmfState() and
236  * stmfLoadConfig().
237  */
238 static int
239 initializeConfig()
240 {
241 	int ret;
242 	stmfState state;
243 
244 
245 	ret = stmfGetState(&state);
246 	if (ret != STMF_STATUS_SUCCESS) {
247 		return (ret);
248 	}
249 
250 	/* if we've already initialized or in the process, return success */
251 	if (state.configState == STMF_CONFIG_STATE_INIT_DONE ||
252 	    state.configState == STMF_CONFIG_STATE_INIT) {
253 		return (STMF_STATUS_SUCCESS);
254 	}
255 
256 	ret = stmfLoadConfig();
257 	if (ret != STMF_STATUS_SUCCESS) {
258 		syslog(LOG_DEBUG,
259 		    "initializeConfig:stmfLoadConfig:error(%d)", ret);
260 		return (ret);
261 	}
262 
263 	ret = stmfGetState(&state);
264 	if (ret != STMF_STATUS_SUCCESS) {
265 		syslog(LOG_DEBUG,
266 		    "initializeConfig:stmfGetState:error(%d)", ret);
267 		return (ret);
268 	}
269 
270 	if (state.configState != STMF_CONFIG_STATE_INIT_DONE) {
271 		syslog(LOG_DEBUG, "initializeConfig:state.configState(%d)",
272 		    state.configState);
273 		ret = STMF_STATUS_ERROR;
274 	}
275 
276 	return (ret);
277 }
278 
279 
280 /*
281  * groupIoctl
282  *
283  * Purpose: issue ioctl for create/delete on group
284  *
285  * cmd - valid STMF ioctl group cmd
286  * groupName - groupName to create or delete
287  */
288 static int
289 groupIoctl(int fd, int cmd, stmfGroupName *groupName)
290 {
291 	int ret = STMF_STATUS_SUCCESS;
292 	int ioctlRet;
293 	stmf_iocdata_t stmfIoctl;
294 	stmf_group_name_t iGroupName;
295 
296 	bzero(&iGroupName, sizeof (iGroupName));
297 
298 	bcopy(groupName, &iGroupName.name, strlen((char *)groupName));
299 
300 	iGroupName.name_size = strlen((char *)groupName);
301 
302 	bzero(&stmfIoctl, sizeof (stmfIoctl));
303 	/*
304 	 * Issue ioctl to create the host group
305 	 */
306 	stmfIoctl.stmf_version = STMF_VERSION_1;
307 	stmfIoctl.stmf_ibuf_size = sizeof (iGroupName);
308 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&iGroupName;
309 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
310 	if (ioctlRet != 0) {
311 		switch (errno) {
312 			case EPERM:
313 			case EACCES:
314 				ret = STMF_ERROR_PERM;
315 				break;
316 			default:
317 				switch (stmfIoctl.stmf_error) {
318 					case STMF_IOCERR_TG_EXISTS:
319 					case STMF_IOCERR_HG_EXISTS:
320 						ret = STMF_ERROR_EXISTS;
321 						break;
322 					case STMF_IOCERR_TG_IN_USE:
323 					case STMF_IOCERR_HG_IN_USE:
324 						ret = STMF_ERROR_GROUP_IN_USE;
325 						break;
326 					case STMF_IOCERR_INVALID_HG:
327 					case STMF_IOCERR_INVALID_TG:
328 						ret = STMF_ERROR_NOT_FOUND;
329 						break;
330 					default:
331 						syslog(LOG_DEBUG,
332 						    "groupIoctl:error(%d)",
333 						    stmfIoctl.stmf_error);
334 						ret = STMF_STATUS_ERROR;
335 						break;
336 				}
337 				break;
338 		}
339 	}
340 done:
341 	return (ret);
342 }
343 
344 /*
345  * groupMemberIoctl
346  *
347  * Purpose: issue ioctl for add/remove member on group
348  *
349  * cmd - valid STMF ioctl group member cmd
350  * groupName - groupName to add to or remove from
351  * devid - group member to add or remove
352  */
353 static int
354 groupMemberIoctl(int fd, int cmd, stmfGroupName *groupName, stmfDevid *devid)
355 {
356 	int ret = STMF_STATUS_SUCCESS;
357 	int ioctlRet;
358 	stmf_iocdata_t stmfIoctl;
359 	stmf_group_op_data_t stmfGroupData;
360 
361 	bzero(&stmfGroupData, sizeof (stmfGroupData));
362 
363 	bcopy(groupName, &stmfGroupData.group.name, strlen((char *)groupName));
364 
365 	stmfGroupData.group.name_size = strlen((char *)groupName);
366 	stmfGroupData.ident[IDENT_LENGTH_BYTE] = devid->identLength;
367 	bcopy(&(devid->ident), &stmfGroupData.ident[IDENT_LENGTH_BYTE + 1],
368 	    devid->identLength);
369 
370 	bzero(&stmfIoctl, sizeof (stmfIoctl));
371 	/*
372 	 * Issue ioctl to add to the host group
373 	 */
374 	stmfIoctl.stmf_version = STMF_VERSION_1;
375 	stmfIoctl.stmf_ibuf_size = sizeof (stmfGroupData);
376 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&stmfGroupData;
377 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
378 	if (ioctlRet != 0) {
379 		switch (errno) {
380 			case EBUSY:
381 				switch (stmfIoctl.stmf_error) {
382 					case STMF_IOCERR_TG_NEED_TG_OFFLINE:
383 						ret = STMF_ERROR_TG_ONLINE;
384 						break;
385 					default:
386 						ret = STMF_ERROR_BUSY;
387 						break;
388 				}
389 				break;
390 			case EPERM:
391 			case EACCES:
392 				ret = STMF_ERROR_PERM;
393 				break;
394 			default:
395 				switch (stmfIoctl.stmf_error) {
396 					case STMF_IOCERR_TG_ENTRY_EXISTS:
397 					case STMF_IOCERR_HG_ENTRY_EXISTS:
398 						ret = STMF_ERROR_EXISTS;
399 						break;
400 					case STMF_IOCERR_INVALID_TG_ENTRY:
401 					case STMF_IOCERR_INVALID_HG_ENTRY:
402 						ret =
403 						    STMF_ERROR_MEMBER_NOT_FOUND;
404 						break;
405 					case STMF_IOCERR_INVALID_TG:
406 					case STMF_IOCERR_INVALID_HG:
407 						ret =
408 						    STMF_ERROR_GROUP_NOT_FOUND;
409 						break;
410 					default:
411 						syslog(LOG_DEBUG,
412 						    "groupMemberIoctl:error"
413 						    "(%d)",
414 						    stmfIoctl.stmf_error);
415 						ret = STMF_STATUS_ERROR;
416 						break;
417 				}
418 				break;
419 		}
420 	}
421 done:
422 	return (ret);
423 }
424 
425 /*
426  * qsort function
427  * sort on veIndex
428  */
429 static int
430 viewEntryCompare(const void *p1, const void *p2)
431 {
432 
433 	stmfViewEntry *v1 = (stmfViewEntry *)p1, *v2 = (stmfViewEntry *)p2;
434 	if (v1->veIndex > v2->veIndex)
435 		return (1);
436 	if (v1->veIndex < v2->veIndex)
437 		return (-1);
438 	return (0);
439 }
440 
441 /*
442  * guidCompare
443  *
444  * qsort function
445  * sort on guid
446  */
447 static int
448 guidCompare(const void *p1, const void *p2)
449 {
450 
451 	stmfGuid *g1 = (stmfGuid *)p1, *g2 = (stmfGuid *)p2;
452 	int i;
453 
454 	for (i = 0; i < sizeof (stmfGuid); i++) {
455 		if (g1->guid[i] > g2->guid[i])
456 			return (1);
457 		if (g1->guid[i] < g2->guid[i])
458 			return (-1);
459 	}
460 
461 	return (0);
462 }
463 
464 /*
465  * stmfAddToHostGroup
466  *
467  * Purpose: Adds an initiator to an existing host group
468  *
469  * hostGroupName - name of an existing host group
470  * hostName - name of initiator to add
471  */
472 int
473 stmfAddToHostGroup(stmfGroupName *hostGroupName, stmfDevid *hostName)
474 {
475 	int ret;
476 	int fd;
477 
478 	if (hostGroupName == NULL ||
479 	    (strnlen((char *)hostGroupName, sizeof (stmfGroupName))
480 	    == sizeof (stmfGroupName)) || hostName == NULL) {
481 		return (STMF_ERROR_INVALID_ARG);
482 	}
483 
484 	/* call init */
485 	ret = initializeConfig();
486 	if (ret != STMF_STATUS_SUCCESS) {
487 		return (ret);
488 	}
489 
490 	/*
491 	 * Open control node for stmf
492 	 */
493 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
494 		return (ret);
495 
496 	if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_HG_ENTRY, hostGroupName,
497 	    hostName)) != STMF_STATUS_SUCCESS) {
498 		goto done;
499 	}
500 
501 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
502 		goto done;
503 	}
504 
505 	ret = psAddHostGroupMember((char *)hostGroupName,
506 	    (char *)hostName->ident);
507 	switch (ret) {
508 		case STMF_PS_SUCCESS:
509 			ret = STMF_STATUS_SUCCESS;
510 			break;
511 		case STMF_PS_ERROR_EXISTS:
512 			ret = STMF_ERROR_EXISTS;
513 			break;
514 		case STMF_PS_ERROR_GROUP_NOT_FOUND:
515 			ret = STMF_ERROR_GROUP_NOT_FOUND;
516 			break;
517 		case STMF_PS_ERROR_BUSY:
518 			ret = STMF_ERROR_BUSY;
519 			break;
520 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
521 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
522 			break;
523 		case STMF_PS_ERROR_VERSION_MISMATCH:
524 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
525 			break;
526 		default:
527 			syslog(LOG_DEBUG,
528 			    "stmfAddToHostGroup:psAddHostGroupMember:error(%d)",
529 			    ret);
530 			ret = STMF_STATUS_ERROR;
531 			break;
532 	}
533 
534 done:
535 	(void) close(fd);
536 	return (ret);
537 }
538 
539 /*
540  * stmfAddToTargetGroup
541  *
542  * Purpose: Adds a local port to an existing target group
543  *
544  * targetGroupName - name of an existing target group
545  * targetName - name of target to add
546  */
547 int
548 stmfAddToTargetGroup(stmfGroupName *targetGroupName, stmfDevid *targetName)
549 {
550 	int ret;
551 	int fd;
552 
553 	if (targetGroupName == NULL ||
554 	    (strnlen((char *)targetGroupName, sizeof (stmfGroupName))
555 	    == sizeof (stmfGroupName)) || targetName == NULL) {
556 		return (STMF_ERROR_INVALID_ARG);
557 	}
558 
559 	/* call init */
560 	ret = initializeConfig();
561 	if (ret != STMF_STATUS_SUCCESS) {
562 		return (ret);
563 	}
564 
565 	/*
566 	 * Open control node for stmf
567 	 */
568 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
569 		return (ret);
570 
571 	if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_TG_ENTRY,
572 	    targetGroupName, targetName)) != STMF_STATUS_SUCCESS) {
573 		goto done;
574 	}
575 
576 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
577 		goto done;
578 	}
579 
580 	ret = psAddTargetGroupMember((char *)targetGroupName,
581 	    (char *)targetName->ident);
582 	switch (ret) {
583 		case STMF_PS_SUCCESS:
584 			ret = STMF_STATUS_SUCCESS;
585 			break;
586 		case STMF_PS_ERROR_EXISTS:
587 			ret = STMF_ERROR_EXISTS;
588 			break;
589 		case STMF_PS_ERROR_GROUP_NOT_FOUND:
590 			ret = STMF_ERROR_GROUP_NOT_FOUND;
591 			break;
592 		case STMF_PS_ERROR_BUSY:
593 			ret = STMF_ERROR_BUSY;
594 			break;
595 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
596 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
597 			break;
598 		case STMF_PS_ERROR_VERSION_MISMATCH:
599 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
600 			break;
601 		default:
602 			syslog(LOG_DEBUG,
603 			    "stmfAddToTargetGroup:psAddTargetGroupMember:"
604 			    "error(%d)", ret);
605 			ret = STMF_STATUS_ERROR;
606 			break;
607 	}
608 
609 done:
610 	(void) close(fd);
611 	return (ret);
612 }
613 
614 /*
615  * addViewEntryIoctl
616  *
617  * Purpose: Issues ioctl to add a view entry
618  *
619  * lu - Logical Unit identifier to which the view entry is added
620  * viewEntry - view entry to add
621  * init - When set to B_TRUE, we are in the init state, i.e. don't call open
622  */
623 static int
624 addViewEntryIoctl(int fd, stmfGuid *lu, stmfViewEntry *viewEntry)
625 {
626 	int ret = STMF_STATUS_SUCCESS;
627 	int ioctlRet;
628 	stmf_iocdata_t stmfIoctl;
629 	stmf_view_op_entry_t ioctlViewEntry;
630 
631 	bzero(&ioctlViewEntry, sizeof (ioctlViewEntry));
632 	/*
633 	 * don't set ve_ndx or ve_ndx_valid as ve_ndx_valid should be
634 	 * false on input
635 	 */
636 	ioctlViewEntry.ve_lu_number_valid = viewEntry->luNbrValid;
637 	ioctlViewEntry.ve_all_hosts = viewEntry->allHosts;
638 	ioctlViewEntry.ve_all_targets = viewEntry->allTargets;
639 
640 	if (viewEntry->allHosts == B_FALSE) {
641 		bcopy(viewEntry->hostGroup, &ioctlViewEntry.ve_host_group.name,
642 		    sizeof (stmfGroupName));
643 		ioctlViewEntry.ve_host_group.name_size =
644 		    strlen((char *)viewEntry->hostGroup);
645 	}
646 	if (viewEntry->allTargets == B_FALSE) {
647 		bcopy(viewEntry->targetGroup,
648 		    &ioctlViewEntry.ve_target_group.name,
649 		    sizeof (stmfGroupName));
650 		ioctlViewEntry.ve_target_group.name_size =
651 		    strlen((char *)viewEntry->targetGroup);
652 	}
653 	if (viewEntry->luNbrValid) {
654 		bcopy(viewEntry->luNbr, &ioctlViewEntry.ve_lu_nbr,
655 		    sizeof (ioctlViewEntry.ve_lu_nbr));
656 	}
657 	bcopy(lu, &ioctlViewEntry.ve_guid, sizeof (stmfGuid));
658 
659 	bzero(&stmfIoctl, sizeof (stmfIoctl));
660 	/*
661 	 * Issue ioctl to add to the view entry
662 	 */
663 	stmfIoctl.stmf_version = STMF_VERSION_1;
664 	stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry);
665 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry;
666 	stmfIoctl.stmf_obuf_size = sizeof (ioctlViewEntry);
667 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&ioctlViewEntry;
668 	ioctlRet = ioctl(fd, STMF_IOCTL_ADD_VIEW_ENTRY, &stmfIoctl);
669 	if (ioctlRet != 0) {
670 		switch (errno) {
671 			case EBUSY:
672 				ret = STMF_ERROR_BUSY;
673 				break;
674 			case EPERM:
675 				ret = STMF_ERROR_PERM;
676 				break;
677 			case EACCES:
678 				switch (stmfIoctl.stmf_error) {
679 					case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
680 						ret = STMF_ERROR_CONFIG_NONE;
681 						break;
682 					default:
683 						ret = STMF_ERROR_PERM;
684 						break;
685 				}
686 				break;
687 			default:
688 				switch (stmfIoctl.stmf_error) {
689 					case STMF_IOCERR_LU_NUMBER_IN_USE:
690 						ret = STMF_ERROR_LUN_IN_USE;
691 						break;
692 					case STMF_IOCERR_VIEW_ENTRY_CONFLICT:
693 						ret = STMF_ERROR_VE_CONFLICT;
694 						break;
695 					case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
696 						ret = STMF_ERROR_CONFIG_NONE;
697 						break;
698 					case STMF_IOCERR_INVALID_HG:
699 						ret = STMF_ERROR_INVALID_HG;
700 						break;
701 					case STMF_IOCERR_INVALID_TG:
702 						ret = STMF_ERROR_INVALID_TG;
703 						break;
704 					default:
705 						syslog(LOG_DEBUG,
706 						    "addViewEntryIoctl"
707 						    ":error(%d)",
708 						    stmfIoctl.stmf_error);
709 						ret = STMF_STATUS_ERROR;
710 						break;
711 				}
712 				break;
713 		}
714 		goto done;
715 	}
716 
717 	/* copy lu nbr back to caller's view entry on success */
718 	viewEntry->veIndex = ioctlViewEntry.ve_ndx;
719 	if (ioctlViewEntry.ve_lu_number_valid) {
720 		bcopy(&ioctlViewEntry.ve_lu_nbr, viewEntry->luNbr,
721 		    sizeof (ioctlViewEntry.ve_lu_nbr));
722 	}
723 	viewEntry->luNbrValid = B_TRUE;
724 
725 done:
726 	return (ret);
727 }
728 
729 /*
730  * stmfAddViewEntry
731  *
732  * Purpose: Adds a view entry to a logical unit
733  *
734  * lu - guid of the logical unit to which the view entry is added
735  * viewEntry - view entry structure to add
736  */
737 int
738 stmfAddViewEntry(stmfGuid *lu, stmfViewEntry *viewEntry)
739 {
740 	int ret;
741 	int fd;
742 	stmfViewEntry iViewEntry;
743 
744 	if (lu == NULL || viewEntry == NULL) {
745 		return (STMF_ERROR_INVALID_ARG);
746 	}
747 
748 	/* initialize and set internal view entry */
749 	bzero(&iViewEntry, sizeof (iViewEntry));
750 
751 	if (!viewEntry->allHosts) {
752 		bcopy(viewEntry->hostGroup, iViewEntry.hostGroup,
753 		    sizeof (iViewEntry.hostGroup));
754 	} else {
755 		iViewEntry.allHosts = B_TRUE;
756 	}
757 
758 	if (!viewEntry->allTargets) {
759 		bcopy(viewEntry->targetGroup, iViewEntry.targetGroup,
760 		    sizeof (iViewEntry.targetGroup));
761 	} else {
762 		iViewEntry.allTargets = B_TRUE;
763 	}
764 
765 	if (viewEntry->luNbrValid) {
766 		iViewEntry.luNbrValid = B_TRUE;
767 		bcopy(viewEntry->luNbr, iViewEntry.luNbr,
768 		    sizeof (iViewEntry.luNbr));
769 	}
770 
771 	/*
772 	 * set users return view entry index valid flag to false
773 	 * in case of failure
774 	 */
775 	viewEntry->veIndexValid = B_FALSE;
776 
777 	/* Check to ensure service exists */
778 	if (psCheckService() != STMF_STATUS_SUCCESS) {
779 		return (STMF_ERROR_SERVICE_NOT_FOUND);
780 	}
781 
782 	/* call init */
783 	ret = initializeConfig();
784 	if (ret != STMF_STATUS_SUCCESS) {
785 		return (ret);
786 	}
787 
788 	/*
789 	 * Open control node for stmf
790 	 */
791 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
792 		return (ret);
793 
794 	/*
795 	 * First add the view entry to the driver
796 	 */
797 	ret = addViewEntryIoctl(fd, lu, &iViewEntry);
798 	if (ret != STMF_STATUS_SUCCESS) {
799 		goto done;
800 	}
801 
802 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
803 		goto done;
804 	}
805 
806 	/*
807 	 * If the add to driver was successful, add it to the persistent
808 	 * store.
809 	 */
810 	ret = psAddViewEntry(lu, &iViewEntry);
811 	switch (ret) {
812 		case STMF_PS_SUCCESS:
813 			ret = STMF_STATUS_SUCCESS;
814 			break;
815 		case STMF_PS_ERROR_NOT_FOUND:
816 			ret = STMF_ERROR_NOT_FOUND;
817 			break;
818 		case STMF_PS_ERROR_BUSY:
819 			ret = STMF_ERROR_BUSY;
820 			break;
821 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
822 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
823 			break;
824 		case STMF_PS_ERROR_VERSION_MISMATCH:
825 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
826 			break;
827 		default:
828 			syslog(LOG_DEBUG,
829 			    "stmfAddViewEntry:psAddViewEntry:error(%d)", ret);
830 			ret = STMF_STATUS_ERROR;
831 			break;
832 	}
833 
834 done:
835 	(void) close(fd);
836 
837 	if (ret == STMF_STATUS_SUCCESS) {
838 		/* set caller's view entry on success */
839 		viewEntry->veIndexValid = iViewEntry.veIndexValid;
840 		viewEntry->veIndex = iViewEntry.veIndex;
841 		viewEntry->luNbrValid = B_TRUE;
842 		bcopy(iViewEntry.luNbr, viewEntry->luNbr,
843 		    sizeof (iViewEntry.luNbr));
844 	}
845 	return (ret);
846 }
847 
848 /*
849  * stmfClearProviderData
850  *
851  * Purpose: delete all provider data for specified provider
852  *
853  * providerName - name of provider for which data should be deleted
854  */
855 int
856 stmfClearProviderData(char *providerName, int providerType)
857 {
858 	int ret;
859 	int fd;
860 	int ioctlRet;
861 	int savedErrno;
862 	stmf_iocdata_t stmfIoctl;
863 	stmf_ppioctl_data_t ppi;
864 
865 	/* call init */
866 	ret = initializeConfig();
867 	if (ret != STMF_STATUS_SUCCESS) {
868 		return (ret);
869 	}
870 
871 	if (providerName == NULL) {
872 		return (STMF_ERROR_INVALID_ARG);
873 	}
874 
875 	if (providerType != STMF_LU_PROVIDER_TYPE &&
876 	    providerType != STMF_PORT_PROVIDER_TYPE) {
877 		return (STMF_ERROR_INVALID_ARG);
878 	}
879 
880 	/*
881 	 * Open control node for stmf
882 	 */
883 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
884 		return (ret);
885 
886 	bzero(&ppi, sizeof (ppi));
887 
888 	(void) strncpy(ppi.ppi_name, providerName, sizeof (ppi.ppi_name));
889 
890 	switch (providerType) {
891 		case STMF_LU_PROVIDER_TYPE:
892 			ppi.ppi_lu_provider = 1;
893 			break;
894 		case STMF_PORT_PROVIDER_TYPE:
895 			ppi.ppi_port_provider = 1;
896 			break;
897 		default:
898 			ret = STMF_ERROR_INVALID_ARG;
899 			goto done;
900 	}
901 
902 	bzero(&stmfIoctl, sizeof (stmfIoctl));
903 
904 	stmfIoctl.stmf_version = STMF_VERSION_1;
905 	stmfIoctl.stmf_ibuf_size = sizeof (stmf_ppioctl_data_t);
906 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ppi;
907 
908 	ioctlRet = ioctl(fd, STMF_IOCTL_CLEAR_PP_DATA, &stmfIoctl);
909 	if (ioctlRet != 0) {
910 		savedErrno = errno;
911 		switch (savedErrno) {
912 			case EBUSY:
913 				ret = STMF_ERROR_BUSY;
914 				break;
915 			case EPERM:
916 			case EACCES:
917 				ret = STMF_ERROR_PERM;
918 				break;
919 			default:
920 				syslog(LOG_DEBUG,
921 				    "stmfClearProviderData:ioctl error(%d)",
922 				    ioctlRet);
923 				ret = STMF_STATUS_ERROR;
924 				break;
925 		}
926 		if (savedErrno != ENOENT) {
927 			goto done;
928 		}
929 	}
930 
931 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
932 		goto done;
933 	}
934 
935 	ret = psClearProviderData(providerName, providerType);
936 	switch (ret) {
937 		case STMF_PS_SUCCESS:
938 			ret = STMF_STATUS_SUCCESS;
939 			break;
940 		case STMF_PS_ERROR_NOT_FOUND:
941 			ret = STMF_ERROR_NOT_FOUND;
942 			break;
943 		case STMF_PS_ERROR_BUSY:
944 			ret = STMF_ERROR_BUSY;
945 			break;
946 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
947 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
948 			break;
949 		case STMF_PS_ERROR_VERSION_MISMATCH:
950 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
951 			break;
952 		default:
953 			syslog(LOG_DEBUG,
954 			    "stmfClearProviderData:psClearProviderData"
955 			    ":error(%d)", ret);
956 			ret = STMF_STATUS_ERROR;
957 			break;
958 	}
959 
960 done:
961 	(void) close(fd);
962 	return (ret);
963 }
964 
965 /*
966  * stmfCreateHostGroup
967  *
968  * Purpose: Create a new initiator group
969  *
970  * hostGroupName - name of host group to create
971  */
972 int
973 stmfCreateHostGroup(stmfGroupName *hostGroupName)
974 {
975 	int ret;
976 	int fd;
977 
978 	if (hostGroupName == NULL ||
979 	    (strnlen((char *)hostGroupName, sizeof (stmfGroupName))
980 	    == sizeof (stmfGroupName))) {
981 		return (STMF_ERROR_INVALID_ARG);
982 	}
983 
984 	/* Check to ensure service exists */
985 	if (psCheckService() != STMF_STATUS_SUCCESS) {
986 		return (STMF_ERROR_SERVICE_NOT_FOUND);
987 	}
988 
989 	/* call init */
990 	ret = initializeConfig();
991 	if (ret != STMF_STATUS_SUCCESS) {
992 		return (ret);
993 	}
994 
995 	/*
996 	 * Open control node for stmf
997 	 */
998 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
999 		return (ret);
1000 
1001 	if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_HOST_GROUP,
1002 	    hostGroupName)) != STMF_STATUS_SUCCESS) {
1003 		goto done;
1004 	}
1005 
1006 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
1007 		goto done;
1008 	}
1009 
1010 	ret = psCreateHostGroup((char *)hostGroupName);
1011 	switch (ret) {
1012 		case STMF_PS_SUCCESS:
1013 			ret = STMF_STATUS_SUCCESS;
1014 			break;
1015 		case STMF_PS_ERROR_EXISTS:
1016 			ret = STMF_ERROR_EXISTS;
1017 			break;
1018 		case STMF_PS_ERROR_BUSY:
1019 			ret = STMF_ERROR_BUSY;
1020 			break;
1021 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
1022 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
1023 			break;
1024 		case STMF_PS_ERROR_VERSION_MISMATCH:
1025 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
1026 			break;
1027 		default:
1028 			syslog(LOG_DEBUG,
1029 			    "stmfCreateHostGroup:psCreateHostGroup:error(%d)",
1030 			    ret);
1031 			ret = STMF_STATUS_ERROR;
1032 			break;
1033 	}
1034 
1035 done:
1036 	(void) close(fd);
1037 	return (ret);
1038 }
1039 
1040 /*
1041  * stmfCreateLu
1042  *
1043  * Purpose: Create a logical unit
1044  *
1045  * hdl - handle to logical unit resource created via stmfCreateLuResource
1046  *
1047  * luGuid - If non-NULL, on success, contains the guid of the created logical
1048  *	    unit
1049  */
1050 int
1051 stmfCreateLu(luResource hdl, stmfGuid *luGuid)
1052 {
1053 	int ret = STMF_STATUS_SUCCESS;
1054 	luResourceImpl *luPropsHdl = hdl;
1055 
1056 	if (hdl == NULL) {
1057 		return (STMF_ERROR_INVALID_ARG);
1058 	}
1059 
1060 	if (luPropsHdl->type == STMF_DISK) {
1061 		ret = createDiskLu((diskResource *)luPropsHdl->resource,
1062 		    luGuid);
1063 	} else {
1064 		return (STMF_ERROR_INVALID_ARG);
1065 	}
1066 
1067 	return (ret);
1068 }
1069 
1070 /*
1071  * stmfCreateLuResource
1072  *
1073  * Purpose: Create resource handle for a logical unit
1074  *
1075  * dType - Type of logical unit resource to create
1076  *	   Can be: STMF_DISK
1077  *
1078  * hdl - pointer to luResource
1079  */
1080 int
1081 stmfCreateLuResource(uint16_t dType, luResource *hdl)
1082 {
1083 	int ret = STMF_STATUS_SUCCESS;
1084 
1085 	if (dType != STMF_DISK || hdl == NULL) {
1086 		return (STMF_ERROR_INVALID_ARG);
1087 	}
1088 
1089 	*hdl = calloc(1, sizeof (luResourceImpl));
1090 	if (*hdl == NULL) {
1091 		return (STMF_ERROR_NOMEM);
1092 	}
1093 
1094 	ret = createDiskResource((luResourceImpl *)*hdl);
1095 	if (ret != STMF_STATUS_SUCCESS) {
1096 		free(*hdl);
1097 		return (ret);
1098 	}
1099 
1100 	return (STMF_STATUS_SUCCESS);
1101 }
1102 
1103 /*
1104  * Creates a disk logical unit
1105  *
1106  * disk - pointer to diskResource structure that represents the properties
1107  *        for the disk logical unit to be created.
1108  */
1109 static int
1110 createDiskLu(diskResource *disk, stmfGuid *createdGuid)
1111 {
1112 	int ret = STMF_STATUS_SUCCESS;
1113 	int dataFileNameLen = 0;
1114 	int metaFileNameLen = 0;
1115 	int serialNumLen = 0;
1116 	int luAliasLen = 0;
1117 	int luMgmtUrlLen = 0;
1118 	int sluBufSize = 0;
1119 	int bufOffset = 0;
1120 	int fd = 0;
1121 	int ioctlRet;
1122 	int savedErrno;
1123 	stmfGuid guid;
1124 	stmf_iocdata_t sbdIoctl = {0};
1125 
1126 	sbd_create_and_reg_lu_t *sbdLu = NULL;
1127 
1128 	/*
1129 	 * Open control node for sbd
1130 	 */
1131 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
1132 		return (ret);
1133 
1134 	/* data file name must be specified */
1135 	if (disk->luDataFileNameValid) {
1136 		dataFileNameLen = strlen(disk->luDataFileName);
1137 	} else {
1138 		(void) close(fd);
1139 		return (STMF_ERROR_MISSING_PROP_VAL);
1140 	}
1141 
1142 	sluBufSize += dataFileNameLen + 1;
1143 
1144 	if (disk->luMetaFileNameValid) {
1145 		metaFileNameLen = strlen(disk->luMetaFileName);
1146 		sluBufSize += metaFileNameLen + 1;
1147 	}
1148 
1149 	serialNumLen = strlen(disk->serialNum);
1150 	sluBufSize += serialNumLen;
1151 
1152 	if (disk->luAliasValid) {
1153 		luAliasLen = strlen(disk->luAlias);
1154 		sluBufSize += luAliasLen + 1;
1155 	}
1156 
1157 	if (disk->luMgmtUrlValid) {
1158 		luMgmtUrlLen = strlen(disk->luMgmtUrl);
1159 		sluBufSize += luMgmtUrlLen + 1;
1160 	}
1161 
1162 	/*
1163 	 * 8 is the size of the buffer set aside for
1164 	 * concatenation of variable length fields
1165 	 */
1166 	sbdLu = (sbd_create_and_reg_lu_t *)calloc(1,
1167 	    sizeof (sbd_create_and_reg_lu_t) + sluBufSize - 8);
1168 	if (sbdLu == NULL) {
1169 		return (STMF_ERROR_NOMEM);
1170 	}
1171 
1172 	sbdLu->slu_struct_size = sizeof (sbd_create_and_reg_lu_t) +
1173 	    sluBufSize - 8;
1174 
1175 	if (metaFileNameLen) {
1176 		sbdLu->slu_meta_fname_valid = 1;
1177 		sbdLu->slu_meta_fname_off = bufOffset;
1178 		bcopy(disk->luMetaFileName, &(sbdLu->slu_buf[bufOffset]),
1179 		    metaFileNameLen + 1);
1180 		bufOffset += metaFileNameLen + 1;
1181 	}
1182 
1183 	bcopy(disk->luDataFileName, &(sbdLu->slu_buf[bufOffset]),
1184 	    dataFileNameLen + 1);
1185 	sbdLu->slu_data_fname_off = bufOffset;
1186 	bufOffset += dataFileNameLen + 1;
1187 
1188 	/* currently, serial # is not passed null terminated to the driver */
1189 	if (disk->serialNumValid) {
1190 		sbdLu->slu_serial_valid = 1;
1191 		sbdLu->slu_serial_off = bufOffset;
1192 		sbdLu->slu_serial_size = serialNumLen;
1193 		bcopy(disk->serialNum, &(sbdLu->slu_buf[bufOffset]),
1194 		    serialNumLen);
1195 		bufOffset += serialNumLen;
1196 	}
1197 
1198 	if (disk->luAliasValid) {
1199 		sbdLu->slu_alias_valid = 1;
1200 		sbdLu->slu_alias_off = bufOffset;
1201 		bcopy(disk->luAlias, &(sbdLu->slu_buf[bufOffset]),
1202 		    luAliasLen + 1);
1203 		bufOffset += luAliasLen + 1;
1204 	}
1205 
1206 	if (disk->luMgmtUrlValid) {
1207 		sbdLu->slu_mgmt_url_valid = 1;
1208 		sbdLu->slu_mgmt_url_off = bufOffset;
1209 		bcopy(disk->luMgmtUrl, &(sbdLu->slu_buf[bufOffset]),
1210 		    luMgmtUrlLen + 1);
1211 		bufOffset += luMgmtUrlLen + 1;
1212 	}
1213 
1214 	if (disk->luSizeValid) {
1215 		sbdLu->slu_lu_size_valid = 1;
1216 		sbdLu->slu_lu_size = disk->luSize;
1217 	}
1218 
1219 	if (disk->luGuidValid) {
1220 		sbdLu->slu_guid_valid = 1;
1221 		bcopy(disk->luGuid, sbdLu->slu_guid, sizeof (disk->luGuid));
1222 	}
1223 
1224 	if (disk->vidValid) {
1225 		sbdLu->slu_vid_valid = 1;
1226 		bcopy(disk->vid, sbdLu->slu_vid, sizeof (disk->vid));
1227 	}
1228 
1229 	if (disk->pidValid) {
1230 		sbdLu->slu_pid_valid = 1;
1231 		bcopy(disk->pid, sbdLu->slu_pid, sizeof (disk->pid));
1232 	}
1233 
1234 	if (disk->revValid) {
1235 		sbdLu->slu_rev_valid = 1;
1236 		bcopy(disk->rev, sbdLu->slu_rev, sizeof (disk->rev));
1237 	}
1238 
1239 	if (disk->companyIdValid) {
1240 		sbdLu->slu_company_id_valid = 1;
1241 		sbdLu->slu_company_id = disk->companyId;
1242 	}
1243 
1244 	if (disk->blkSizeValid) {
1245 		sbdLu->slu_blksize_valid = 1;
1246 		sbdLu->slu_blksize = disk->blkSize;
1247 	}
1248 
1249 	if (disk->writeProtectEnableValid) {
1250 		if (disk->writeProtectEnable) {
1251 			sbdLu->slu_write_protected = 1;
1252 		}
1253 	}
1254 
1255 	if (disk->writebackCacheDisableValid) {
1256 		sbdLu->slu_writeback_cache_disable_valid = 1;
1257 		if (disk->writebackCacheDisable) {
1258 			sbdLu->slu_writeback_cache_disable = 1;
1259 		}
1260 	}
1261 
1262 	sbdIoctl.stmf_version = STMF_VERSION_1;
1263 	sbdIoctl.stmf_ibuf_size = sbdLu->slu_struct_size;
1264 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdLu;
1265 	sbdIoctl.stmf_obuf_size = sbdLu->slu_struct_size;
1266 	sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdLu;
1267 
1268 	ioctlRet = ioctl(fd, SBD_IOCTL_CREATE_AND_REGISTER_LU, &sbdIoctl);
1269 	if (ioctlRet != 0) {
1270 		savedErrno = errno;
1271 		switch (savedErrno) {
1272 			case EBUSY:
1273 				ret = STMF_ERROR_BUSY;
1274 				break;
1275 			case EPERM:
1276 			case EACCES:
1277 				ret = STMF_ERROR_PERM;
1278 				break;
1279 			default:
1280 				diskError(sbdIoctl.stmf_error, &ret);
1281 				if (ret == STMF_STATUS_ERROR) {
1282 					syslog(LOG_DEBUG,
1283 					"createDiskLu:ioctl "
1284 					"error(%d) (%d) (%d)", ioctlRet,
1285 					    sbdIoctl.stmf_error, savedErrno);
1286 				}
1287 				break;
1288 		}
1289 	}
1290 
1291 	if (ret != STMF_STATUS_SUCCESS) {
1292 		goto done;
1293 	}
1294 
1295 	/*
1296 	 * on success, copy the resulting guid into the caller's guid if not
1297 	 * NULL
1298 	 */
1299 	if (createdGuid) {
1300 		bcopy(sbdLu->slu_guid, createdGuid->guid,
1301 		    sizeof (sbdLu->slu_guid));
1302 	}
1303 
1304 	bcopy(sbdLu->slu_guid, guid.guid, sizeof (sbdLu->slu_guid));
1305 	if (disk->luMetaFileNameValid) {
1306 		ret = addGuidToDiskStore(&guid, disk->luMetaFileName);
1307 	} else {
1308 		ret = addGuidToDiskStore(&guid, disk->luDataFileName);
1309 	}
1310 done:
1311 	free(sbdLu);
1312 	(void) close(fd);
1313 	return (ret);
1314 }
1315 
1316 
1317 /*
1318  * stmfImportLu
1319  *
1320  * Purpose: Import a previously created logical unit
1321  *
1322  * dType - Type of logical unit
1323  *         Can be: STMF_DISK
1324  *
1325  * luGuid - If non-NULL, on success, contains the guid of the imported logical
1326  *	    unit
1327  *
1328  * fname - A file name where the metadata resides
1329  *
1330  */
1331 int
1332 stmfImportLu(uint16_t dType, char *fname, stmfGuid *luGuid)
1333 {
1334 	int ret = STMF_STATUS_SUCCESS;
1335 
1336 	if (dType == STMF_DISK) {
1337 		ret = importDiskLu(fname, luGuid);
1338 	} else {
1339 		return (STMF_ERROR_INVALID_ARG);
1340 	}
1341 
1342 	return (ret);
1343 }
1344 
1345 /*
1346  * importDiskLu
1347  *
1348  * filename - filename to import
1349  * createdGuid - if not NULL, on success contains the imported guid
1350  *
1351  */
1352 static int
1353 importDiskLu(char *fname, stmfGuid *createdGuid)
1354 {
1355 	int ret = STMF_STATUS_SUCCESS;
1356 	int fd = 0;
1357 	int ioctlRet;
1358 	int savedErrno;
1359 	int metaFileNameLen;
1360 	stmfGuid iGuid;
1361 	int iluBufSize = 0;
1362 	sbd_import_lu_t *sbdLu = NULL;
1363 	stmf_iocdata_t sbdIoctl = {0};
1364 
1365 	if (fname == NULL) {
1366 		return (STMF_ERROR_INVALID_ARG);
1367 	}
1368 
1369 	/*
1370 	 * Open control node for sbd
1371 	 */
1372 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
1373 		return (ret);
1374 
1375 	metaFileNameLen = strlen(fname);
1376 	iluBufSize += metaFileNameLen + 1;
1377 
1378 	/*
1379 	 * 8 is the size of the buffer set aside for
1380 	 * concatenation of variable length fields
1381 	 */
1382 	sbdLu = (sbd_import_lu_t *)calloc(1,
1383 	    sizeof (sbd_import_lu_t) + iluBufSize - 8);
1384 	if (sbdLu == NULL) {
1385 		(void) close(fd);
1386 		return (STMF_ERROR_NOMEM);
1387 	}
1388 
1389 	/*
1390 	 * Accept either a data file or meta data file.
1391 	 * sbd will do the right thing here either way.
1392 	 * i.e. if it's a data file, it assumes that the
1393 	 * meta data is shared with the data.
1394 	 */
1395 	(void) strncpy(sbdLu->ilu_meta_fname, fname, metaFileNameLen);
1396 
1397 	sbdLu->ilu_struct_size = sizeof (sbd_import_lu_t) + iluBufSize - 8;
1398 
1399 	sbdIoctl.stmf_version = STMF_VERSION_1;
1400 	sbdIoctl.stmf_ibuf_size = sbdLu->ilu_struct_size;
1401 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdLu;
1402 	sbdIoctl.stmf_obuf_size = sbdLu->ilu_struct_size;
1403 	sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdLu;
1404 
1405 	ioctlRet = ioctl(fd, SBD_IOCTL_IMPORT_LU, &sbdIoctl);
1406 	if (ioctlRet != 0) {
1407 		savedErrno = errno;
1408 		switch (savedErrno) {
1409 			case EBUSY:
1410 				ret = STMF_ERROR_BUSY;
1411 				break;
1412 			case EPERM:
1413 			case EACCES:
1414 				ret = STMF_ERROR_PERM;
1415 				break;
1416 			default:
1417 				diskError(sbdIoctl.stmf_error, &ret);
1418 				if (ret == STMF_STATUS_ERROR) {
1419 					syslog(LOG_DEBUG,
1420 					"importDiskLu:ioctl "
1421 					"error(%d) (%d) (%d)", ioctlRet,
1422 					    sbdIoctl.stmf_error, savedErrno);
1423 				}
1424 				break;
1425 		}
1426 	}
1427 
1428 	if (ret != STMF_STATUS_SUCCESS) {
1429 		goto done;
1430 	}
1431 
1432 	/*
1433 	 * on success, copy the resulting guid into the caller's guid if not
1434 	 * NULL and add it to the persistent store for sbd
1435 	 */
1436 	if (createdGuid) {
1437 		bcopy(sbdLu->ilu_ret_guid, createdGuid->guid,
1438 		    sizeof (sbdLu->ilu_ret_guid));
1439 		ret = addGuidToDiskStore(createdGuid, fname);
1440 	} else {
1441 		bcopy(sbdLu->ilu_ret_guid, iGuid.guid,
1442 		    sizeof (sbdLu->ilu_ret_guid));
1443 		ret = addGuidToDiskStore(&iGuid, fname);
1444 	}
1445 done:
1446 	free(sbdLu);
1447 	(void) close(fd);
1448 	return (ret);
1449 }
1450 
1451 /*
1452  * diskError
1453  *
1454  * Purpose: Translate sbd driver error
1455  */
1456 static void
1457 diskError(uint32_t stmfError, int *ret)
1458 {
1459 	switch (stmfError) {
1460 		case SBD_RET_META_CREATION_FAILED:
1461 		case SBD_RET_ZFS_META_CREATE_FAILED:
1462 			*ret = STMF_ERROR_META_CREATION;
1463 			break;
1464 		case SBD_RET_INVALID_BLKSIZE:
1465 			*ret = STMF_ERROR_INVALID_BLKSIZE;
1466 			break;
1467 		case SBD_RET_FILE_ALREADY_REGISTERED:
1468 			*ret = STMF_ERROR_FILE_IN_USE;
1469 			break;
1470 		case SBD_RET_GUID_ALREADY_REGISTERED:
1471 			*ret = STMF_ERROR_GUID_IN_USE;
1472 			break;
1473 		case SBD_RET_META_PATH_NOT_ABSOLUTE:
1474 		case SBD_RET_META_FILE_LOOKUP_FAILED:
1475 		case SBD_RET_META_FILE_OPEN_FAILED:
1476 		case SBD_RET_META_FILE_GETATTR_FAILED:
1477 		case SBD_RET_NO_META:
1478 			*ret = STMF_ERROR_META_FILE_NAME;
1479 			break;
1480 		case SBD_RET_DATA_PATH_NOT_ABSOLUTE:
1481 		case SBD_RET_DATA_FILE_LOOKUP_FAILED:
1482 		case SBD_RET_DATA_FILE_OPEN_FAILED:
1483 		case SBD_RET_DATA_FILE_GETATTR_FAILED:
1484 			*ret = STMF_ERROR_DATA_FILE_NAME;
1485 			break;
1486 		case SBD_RET_FILE_SIZE_ERROR:
1487 			*ret = STMF_ERROR_FILE_SIZE_INVALID;
1488 			break;
1489 		case SBD_RET_SIZE_OUT_OF_RANGE:
1490 			*ret = STMF_ERROR_SIZE_OUT_OF_RANGE;
1491 			break;
1492 		case SBD_RET_LU_BUSY:
1493 			*ret = STMF_ERROR_LU_BUSY;
1494 			break;
1495 		case SBD_RET_WRITE_CACHE_SET_FAILED:
1496 			*ret = STMF_ERROR_WRITE_CACHE_SET;
1497 			break;
1498 		case SBD_RET_ACCESS_STATE_FAILED:
1499 			*ret = STMF_ERROR_ACCESS_STATE_SET;
1500 			break;
1501 		default:
1502 			*ret = STMF_STATUS_ERROR;
1503 			break;
1504 	}
1505 }
1506 
1507 /*
1508  * Creates a logical unit resource of type STMF_DISK.
1509  *
1510  * No defaults should be set here as all defaults are derived from the
1511  * driver's default settings.
1512  */
1513 static int
1514 createDiskResource(luResourceImpl *hdl)
1515 {
1516 	hdl->type = STMF_DISK;
1517 
1518 	hdl->resource = calloc(1, sizeof (diskResource));
1519 	if (hdl->resource == NULL) {
1520 		return (STMF_ERROR_NOMEM);
1521 	}
1522 
1523 	return (STMF_STATUS_SUCCESS);
1524 }
1525 
1526 /*
1527  * stmfDeleteLu
1528  *
1529  * Purpose: Delete a logical unit
1530  *
1531  * hdl - handle to logical unit resource created via stmfCreateLuResource
1532  *
1533  * luGuid - If non-NULL, on success, contains the guid of the created logical
1534  *	    unit
1535  */
1536 int
1537 stmfDeleteLu(stmfGuid *luGuid)
1538 {
1539 	int ret = STMF_STATUS_SUCCESS;
1540 	stmfLogicalUnitProperties luProps;
1541 
1542 	if (luGuid == NULL) {
1543 		return (STMF_ERROR_INVALID_ARG);
1544 	}
1545 
1546 	/* Check logical unit provider name to call correct dtype function */
1547 	if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps))
1548 	    != STMF_STATUS_SUCCESS) {
1549 		return (ret);
1550 	} else {
1551 		if (strcmp(luProps.providerName, "sbd") == 0) {
1552 			ret = deleteDiskLu(luGuid);
1553 		} else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) {
1554 			return (STMF_ERROR_NOT_FOUND);
1555 		} else {
1556 			return (STMF_ERROR_INVALID_ARG);
1557 		}
1558 	}
1559 
1560 	return (ret);
1561 }
1562 
1563 static int
1564 deleteDiskLu(stmfGuid *luGuid)
1565 {
1566 	int ret = STMF_STATUS_SUCCESS;
1567 	int fd;
1568 	int savedErrno;
1569 	int ioctlRet;
1570 	sbd_delete_lu_t deleteLu = {0};
1571 
1572 	stmf_iocdata_t sbdIoctl = {0};
1573 
1574 	/*
1575 	 * Open control node for sbd
1576 	 */
1577 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
1578 		return (ret);
1579 
1580 	ret = removeGuidFromDiskStore(luGuid);
1581 	if (ret != STMF_STATUS_SUCCESS) {
1582 		goto done;
1583 	}
1584 
1585 	bcopy(luGuid, deleteLu.dlu_guid, sizeof (deleteLu.dlu_guid));
1586 	deleteLu.dlu_by_guid = 1;
1587 
1588 	sbdIoctl.stmf_version = STMF_VERSION_1;
1589 	sbdIoctl.stmf_ibuf_size = sizeof (deleteLu);
1590 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)&deleteLu;
1591 	ioctlRet = ioctl(fd, SBD_IOCTL_DELETE_LU, &sbdIoctl);
1592 	if (ioctlRet != 0) {
1593 		savedErrno = errno;
1594 		switch (savedErrno) {
1595 			case EBUSY:
1596 				ret = STMF_ERROR_BUSY;
1597 				break;
1598 			case EPERM:
1599 			case EACCES:
1600 				ret = STMF_ERROR_PERM;
1601 				break;
1602 			case ENOENT:
1603 				ret = STMF_ERROR_NOT_FOUND;
1604 				break;
1605 			default:
1606 				syslog(LOG_DEBUG,
1607 				    "deleteDiskLu:ioctl error(%d) (%d) (%d)",
1608 				    ioctlRet, sbdIoctl.stmf_error, savedErrno);
1609 				ret = STMF_STATUS_ERROR;
1610 				break;
1611 		}
1612 	}
1613 
1614 done:
1615 	(void) close(fd);
1616 	return (ret);
1617 }
1618 
1619 /*
1620  * stmfLuStandby
1621  *
1622  * Purpose: Sets access state to standby
1623  *
1624  * luGuid - guid of registered logical unit
1625  *
1626  */
1627 int
1628 stmfLuStandby(stmfGuid *luGuid)
1629 {
1630 	int ret = STMF_STATUS_SUCCESS;
1631 	stmfLogicalUnitProperties luProps;
1632 
1633 	if (luGuid == NULL) {
1634 		return (STMF_ERROR_INVALID_ARG);
1635 	}
1636 
1637 	/* Check logical unit provider name to call correct dtype function */
1638 	if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps))
1639 	    != STMF_STATUS_SUCCESS) {
1640 		return (ret);
1641 	} else {
1642 		if (strcmp(luProps.providerName, "sbd") == 0) {
1643 			ret = setDiskStandby(luGuid);
1644 		} else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) {
1645 			return (STMF_ERROR_NOT_FOUND);
1646 		} else {
1647 			return (STMF_ERROR_INVALID_ARG);
1648 		}
1649 	}
1650 
1651 	return (ret);
1652 }
1653 
1654 static int
1655 setDiskStandby(stmfGuid *luGuid)
1656 {
1657 	int ret = STMF_STATUS_SUCCESS;
1658 	stmf_iocdata_t sbdIoctl = {0};
1659 	sbd_set_lu_standby_t sbdLu = {0};
1660 	int ioctlRet;
1661 	int savedErrno;
1662 	int fd = 0;
1663 
1664 	/*
1665 	 * Open control node for sbd
1666 	 */
1667 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
1668 		return (ret);
1669 
1670 	bcopy(luGuid, &sbdLu.stlu_guid, sizeof (stmfGuid));
1671 
1672 	sbdIoctl.stmf_version = STMF_VERSION_1;
1673 	sbdIoctl.stmf_ibuf_size = sizeof (sbd_set_lu_standby_t);
1674 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)&sbdLu;
1675 
1676 	ioctlRet = ioctl(fd, SBD_IOCTL_SET_LU_STANDBY, &sbdIoctl);
1677 	if (ioctlRet != 0) {
1678 		savedErrno = errno;
1679 		switch (savedErrno) {
1680 			case EBUSY:
1681 				ret = STMF_ERROR_BUSY;
1682 				break;
1683 			case EPERM:
1684 			case EACCES:
1685 				ret = STMF_ERROR_PERM;
1686 				break;
1687 			default:
1688 				diskError(sbdIoctl.stmf_error, &ret);
1689 				if (ret == STMF_STATUS_ERROR) {
1690 					syslog(LOG_DEBUG,
1691 					"setDiskStandby:ioctl "
1692 					"error(%d) (%d) (%d)", ioctlRet,
1693 					    sbdIoctl.stmf_error, savedErrno);
1694 				}
1695 				break;
1696 		}
1697 	}
1698 	return (ret);
1699 }
1700 
1701 /*
1702  * stmfModifyLu
1703  *
1704  * Purpose: Modify properties of a logical unit
1705  *
1706  * luGuid - guid of registered logical unit
1707  * prop - property to modify
1708  * propVal - property value to set
1709  *
1710  */
1711 int
1712 stmfModifyLu(stmfGuid *luGuid, uint32_t prop, const char *propVal)
1713 {
1714 	int ret = STMF_STATUS_SUCCESS;
1715 	stmfLogicalUnitProperties luProps;
1716 
1717 	if (luGuid == NULL) {
1718 		return (STMF_ERROR_INVALID_ARG);
1719 	}
1720 
1721 	/* Check logical unit provider name to call correct dtype function */
1722 	if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps))
1723 	    != STMF_STATUS_SUCCESS) {
1724 		return (ret);
1725 	} else {
1726 		if (strcmp(luProps.providerName, "sbd") == 0) {
1727 			ret = modifyDiskLuProp(luGuid, NULL, prop, propVal);
1728 		} else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) {
1729 			return (STMF_ERROR_NOT_FOUND);
1730 		} else {
1731 			return (STMF_ERROR_INVALID_ARG);
1732 		}
1733 	}
1734 
1735 	return (ret);
1736 }
1737 
1738 /*
1739  * stmfModifyLuByFname
1740  *
1741  * Purpose: Modify a device by filename. Device does not need to be registered.
1742  *
1743  * dType - type of device to modify
1744  *         STMF_DISK
1745  *
1746  * fname - filename or meta filename
1747  * prop - valid property identifier
1748  * propVal - property value
1749  *
1750  */
1751 int
1752 stmfModifyLuByFname(uint16_t dType, const char *fname, uint32_t prop,
1753     const char *propVal)
1754 {
1755 	int ret = STMF_STATUS_SUCCESS;
1756 	if (fname == NULL) {
1757 		return (STMF_ERROR_INVALID_ARG);
1758 	}
1759 
1760 	if (dType == STMF_DISK) {
1761 		ret = modifyDiskLuProp(NULL, fname, prop, propVal);
1762 	} else {
1763 		return (STMF_ERROR_INVALID_ARG);
1764 	}
1765 
1766 	return (ret);
1767 }
1768 
1769 static int
1770 modifyDiskLuProp(stmfGuid *luGuid, const char *fname, uint32_t prop,
1771     const char *propVal)
1772 {
1773 	int ret = STMF_STATUS_SUCCESS;
1774 	luResource hdl = NULL;
1775 	luResourceImpl *luPropsHdl;
1776 
1777 	ret = stmfCreateLuResource(STMF_DISK, &hdl);
1778 	if (ret != STMF_STATUS_SUCCESS) {
1779 		return (ret);
1780 	}
1781 	ret = validateModifyDiskProp(prop);
1782 	if (ret != STMF_STATUS_SUCCESS) {
1783 		(void) stmfFreeLuResource(hdl);
1784 		return (STMF_ERROR_INVALID_PROP);
1785 	}
1786 	ret = stmfSetLuProp(hdl, prop, propVal);
1787 	if (ret != STMF_STATUS_SUCCESS) {
1788 		(void) stmfFreeLuResource(hdl);
1789 		return (ret);
1790 	}
1791 	luPropsHdl = hdl;
1792 	ret = modifyDiskLu((diskResource *)luPropsHdl->resource, luGuid, fname);
1793 	(void) stmfFreeLuResource(hdl);
1794 	return (ret);
1795 }
1796 
1797 static int
1798 validateModifyDiskProp(uint32_t prop)
1799 {
1800 	switch (prop) {
1801 		case STMF_LU_PROP_ALIAS:
1802 		case STMF_LU_PROP_SIZE:
1803 		case STMF_LU_PROP_MGMT_URL:
1804 		case STMF_LU_PROP_WRITE_PROTECT:
1805 		case STMF_LU_PROP_WRITE_CACHE_DISABLE:
1806 			return (STMF_STATUS_SUCCESS);
1807 			break;
1808 		default:
1809 			return (STMF_STATUS_ERROR);
1810 			break;
1811 	}
1812 }
1813 
1814 static int
1815 modifyDiskLu(diskResource *disk, stmfGuid *luGuid, const char *fname)
1816 {
1817 	int ret = STMF_STATUS_SUCCESS;
1818 	int luAliasLen = 0;
1819 	int luMgmtUrlLen = 0;
1820 	int mluBufSize = 0;
1821 	int bufOffset = 0;
1822 	int fd = 0;
1823 	int ioctlRet;
1824 	int savedErrno;
1825 	int fnameSize = 0;
1826 	stmf_iocdata_t sbdIoctl = {0};
1827 
1828 	sbd_modify_lu_t *sbdLu = NULL;
1829 
1830 	if (luGuid == NULL && fname == NULL) {
1831 		return (STMF_ERROR_INVALID_ARG);
1832 	}
1833 
1834 	if (fname) {
1835 		fnameSize = strlen(fname) + 1;
1836 		mluBufSize += fnameSize;
1837 	}
1838 
1839 	/*
1840 	 * Open control node for sbd
1841 	 */
1842 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
1843 		return (ret);
1844 
1845 	if (disk->luAliasValid) {
1846 		luAliasLen = strlen(disk->luAlias);
1847 		mluBufSize += luAliasLen + 1;
1848 	}
1849 
1850 	if (disk->luMgmtUrlValid) {
1851 		luMgmtUrlLen = strlen(disk->luMgmtUrl);
1852 		mluBufSize += luMgmtUrlLen + 1;
1853 	}
1854 
1855 	/*
1856 	 * 8 is the size of the buffer set aside for
1857 	 * concatenation of variable length fields
1858 	 */
1859 	sbdLu = (sbd_modify_lu_t *)calloc(1,
1860 	    sizeof (sbd_modify_lu_t) + mluBufSize - 8 + fnameSize);
1861 	if (sbdLu == NULL) {
1862 		(void) close(fd);
1863 		return (STMF_ERROR_NOMEM);
1864 	}
1865 
1866 	sbdLu->mlu_struct_size = sizeof (sbd_modify_lu_t) +
1867 	    mluBufSize - 8 + fnameSize;
1868 
1869 	if (disk->luAliasValid) {
1870 		sbdLu->mlu_alias_valid = 1;
1871 		sbdLu->mlu_alias_off = bufOffset;
1872 		bcopy(disk->luAlias, &(sbdLu->mlu_buf[bufOffset]),
1873 		    luAliasLen + 1);
1874 		bufOffset += luAliasLen + 1;
1875 	}
1876 
1877 	if (disk->luMgmtUrlValid) {
1878 		sbdLu->mlu_mgmt_url_valid = 1;
1879 		sbdLu->mlu_mgmt_url_off = bufOffset;
1880 		bcopy(disk->luMgmtUrl, &(sbdLu->mlu_buf[bufOffset]),
1881 		    luMgmtUrlLen + 1);
1882 		bufOffset += luMgmtUrlLen + 1;
1883 	}
1884 
1885 	if (disk->luSizeValid) {
1886 		sbdLu->mlu_lu_size_valid = 1;
1887 		sbdLu->mlu_lu_size = disk->luSize;
1888 	}
1889 
1890 	if (disk->writeProtectEnableValid) {
1891 		sbdLu->mlu_write_protected_valid = 1;
1892 		if (disk->writeProtectEnable) {
1893 			sbdLu->mlu_write_protected = 1;
1894 		}
1895 	}
1896 
1897 	if (disk->writebackCacheDisableValid) {
1898 		sbdLu->mlu_writeback_cache_disable_valid = 1;
1899 		if (disk->writebackCacheDisable) {
1900 			sbdLu->mlu_writeback_cache_disable = 1;
1901 		}
1902 	}
1903 
1904 	if (luGuid) {
1905 		bcopy(luGuid, sbdLu->mlu_input_guid, sizeof (stmfGuid));
1906 		sbdLu->mlu_by_guid = 1;
1907 	} else {
1908 		sbdLu->mlu_fname_off = bufOffset;
1909 		bcopy(fname, &(sbdLu->mlu_buf[bufOffset]), fnameSize + 1);
1910 		sbdLu->mlu_by_fname = 1;
1911 	}
1912 
1913 	sbdIoctl.stmf_version = STMF_VERSION_1;
1914 	sbdIoctl.stmf_ibuf_size = sbdLu->mlu_struct_size;
1915 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdLu;
1916 
1917 	ioctlRet = ioctl(fd, SBD_IOCTL_MODIFY_LU, &sbdIoctl);
1918 	if (ioctlRet != 0) {
1919 		savedErrno = errno;
1920 		switch (savedErrno) {
1921 			case EBUSY:
1922 				ret = STMF_ERROR_BUSY;
1923 				break;
1924 			case EPERM:
1925 			case EACCES:
1926 				ret = STMF_ERROR_PERM;
1927 				break;
1928 			default:
1929 				diskError(sbdIoctl.stmf_error, &ret);
1930 				if (ret == STMF_STATUS_ERROR) {
1931 					syslog(LOG_DEBUG,
1932 					"modifyDiskLu:ioctl "
1933 					"error(%d) (%d) (%d)", ioctlRet,
1934 					    sbdIoctl.stmf_error, savedErrno);
1935 				}
1936 				break;
1937 		}
1938 	}
1939 
1940 	if (ret != STMF_STATUS_SUCCESS) {
1941 		goto done;
1942 	}
1943 
1944 done:
1945 	free(sbdLu);
1946 	(void) close(fd);
1947 	return (ret);
1948 }
1949 
1950 /*
1951  * removeGuidFromDiskStore
1952  *
1953  * Purpose: delete a logical unit from the sbd provider data
1954  */
1955 static int
1956 removeGuidFromDiskStore(stmfGuid *guid)
1957 {
1958 	return (persistDiskGuid(guid, NULL, B_FALSE));
1959 }
1960 
1961 
1962 /*
1963  * addGuidToDiskStore
1964  *
1965  * Purpose: add a logical unit to the sbd provider data
1966  */
1967 static int
1968 addGuidToDiskStore(stmfGuid *guid, char *filename)
1969 {
1970 	return (persistDiskGuid(guid, filename, B_TRUE));
1971 }
1972 
1973 
1974 /*
1975  * persistDiskGuid
1976  *
1977  * Purpose: Persist or unpersist a guid for the sbd provider data
1978  *
1979  */
1980 static int
1981 persistDiskGuid(stmfGuid *guid, char *filename, boolean_t persist)
1982 {
1983 	char	    guidAsciiBuf[LU_ASCII_GUID_SIZE + 1] = {0};
1984 	nvlist_t    *nvl = NULL;
1985 
1986 	uint64_t    setToken;
1987 	boolean_t   retryGetProviderData = B_FALSE;
1988 	boolean_t   newData = B_FALSE;
1989 	int	    ret = STMF_STATUS_SUCCESS;
1990 	int	    retryCnt = 0;
1991 	int	    stmfRet;
1992 
1993 	/* if we're persisting a guid, there must be a filename */
1994 	if (persist && !filename) {
1995 		return (1);
1996 	}
1997 
1998 	/* guid is stored in lowercase ascii hex */
1999 	(void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf),
2000 	    "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
2001 	    "%02x%02x%02x%02x%02x%02x",
2002 	    guid->guid[0], guid->guid[1], guid->guid[2], guid->guid[3],
2003 	    guid->guid[4], guid->guid[5], guid->guid[6], guid->guid[7],
2004 	    guid->guid[8], guid->guid[9], guid->guid[10], guid->guid[11],
2005 	    guid->guid[12], guid->guid[13], guid->guid[14], guid->guid[15]);
2006 
2007 
2008 	do {
2009 		retryGetProviderData = B_FALSE;
2010 		stmfRet = stmfGetProviderDataProt("sbd", &nvl,
2011 		    STMF_LU_PROVIDER_TYPE, &setToken);
2012 		if (stmfRet != STMF_STATUS_SUCCESS) {
2013 			if (persist && stmfRet == STMF_ERROR_NOT_FOUND) {
2014 				ret = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0);
2015 				if (ret != 0) {
2016 					syslog(LOG_DEBUG,
2017 					    "unpersistGuid:nvlist_alloc(%d)",
2018 					    ret);
2019 					ret = STMF_STATUS_ERROR;
2020 					goto done;
2021 				}
2022 				newData = B_TRUE;
2023 			} else {
2024 				/*
2025 				 * if we're persisting the data, it's
2026 				 * an error. Otherwise, just return
2027 				 */
2028 				if (persist) {
2029 					ret = stmfRet;
2030 				}
2031 				goto done;
2032 			}
2033 		}
2034 		if (persist) {
2035 			ret = nvlist_add_string(nvl, guidAsciiBuf, filename);
2036 		} else {
2037 			ret = nvlist_remove(nvl, guidAsciiBuf,
2038 			    DATA_TYPE_STRING);
2039 			if (ret == ENOENT) {
2040 				ret = 0;
2041 			}
2042 		}
2043 		if (ret == 0) {
2044 			if (newData) {
2045 				stmfRet = stmfSetProviderDataProt("sbd", nvl,
2046 				    STMF_LU_PROVIDER_TYPE, NULL);
2047 			} else {
2048 				stmfRet = stmfSetProviderDataProt("sbd", nvl,
2049 				    STMF_LU_PROVIDER_TYPE, &setToken);
2050 			}
2051 			if (stmfRet != STMF_STATUS_SUCCESS) {
2052 				if (stmfRet == STMF_ERROR_BUSY) {
2053 					/* get/set failed, try again */
2054 					retryGetProviderData = B_TRUE;
2055 					if (retryCnt++ > MAX_PROVIDER_RETRY) {
2056 						ret = stmfRet;
2057 						break;
2058 					}
2059 					continue;
2060 				} else if (stmfRet ==
2061 				    STMF_ERROR_PROV_DATA_STALE) {
2062 					/* update failed, try again */
2063 					nvlist_free(nvl);
2064 					nvl = NULL;
2065 					retryGetProviderData = B_TRUE;
2066 					if (retryCnt++ > MAX_PROVIDER_RETRY) {
2067 						ret = stmfRet;
2068 						break;
2069 					}
2070 					continue;
2071 				} else {
2072 					syslog(LOG_DEBUG,
2073 					    "unpersistGuid:error(%x)", stmfRet);
2074 					ret = stmfRet;
2075 				}
2076 				break;
2077 			}
2078 		} else {
2079 			syslog(LOG_DEBUG,
2080 			    "unpersistGuid:error nvlist_add/remove(%d)",
2081 			    ret);
2082 			ret = STMF_STATUS_ERROR;
2083 		}
2084 	} while (retryGetProviderData);
2085 
2086 done:
2087 	nvlist_free(nvl);
2088 	return (ret);
2089 }
2090 
2091 
2092 /*
2093  * stmfGetLuProp
2094  *
2095  * Purpose: Get current value for a resource property
2096  *
2097  * hdl - luResource from a previous call to stmfCreateLuResource
2098  *
2099  * resourceProp - a valid resource property type
2100  *
2101  * propVal - void pointer to a pointer of the value to be retrieved
2102  */
2103 int
2104 stmfGetLuProp(luResource hdl, uint32_t prop, char *propVal, size_t *propLen)
2105 {
2106 	int ret = STMF_STATUS_SUCCESS;
2107 	luResourceImpl *luPropsHdl = hdl;
2108 	if (hdl == NULL || propLen == NULL || propVal == NULL) {
2109 		return (STMF_ERROR_INVALID_ARG);
2110 	}
2111 
2112 	if (luPropsHdl->type == STMF_DISK) {
2113 		ret = getDiskProp(luPropsHdl, prop, propVal, propLen);
2114 	} else {
2115 		return (STMF_ERROR_INVALID_ARG);
2116 	}
2117 
2118 	return (ret);
2119 }
2120 
2121 /*
2122  * stmfGetLuResource
2123  *
2124  * Purpose: Get a logical unit resource handle for a given logical unit.
2125  *
2126  * hdl - pointer to luResource
2127  */
2128 int
2129 stmfGetLuResource(stmfGuid *luGuid, luResource *hdl)
2130 {
2131 	int ret = STMF_STATUS_SUCCESS;
2132 	stmfLogicalUnitProperties luProps;
2133 
2134 
2135 	/* Check logical unit provider name to call correct dtype function */
2136 	if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps))
2137 	    != STMF_STATUS_SUCCESS) {
2138 		return (ret);
2139 	} else {
2140 		if (strcmp(luProps.providerName, "sbd") == 0) {
2141 			ret = getDiskAllProps(luGuid, hdl);
2142 		} else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) {
2143 			return (STMF_ERROR_NOT_FOUND);
2144 		} else {
2145 			return (STMF_ERROR_INVALID_ARG);
2146 		}
2147 	}
2148 
2149 	return (ret);
2150 }
2151 
2152 /*
2153  * getDiskAllProps
2154  *
2155  * Purpose: load all disk properties from sbd driver
2156  *
2157  * luGuid - guid of disk device for which properties are to be retrieved
2158  * hdl - allocated luResource into which properties are to be copied
2159  *
2160  */
2161 static int
2162 getDiskAllProps(stmfGuid *luGuid, luResource *hdl)
2163 {
2164 	int ret = STMF_STATUS_SUCCESS;
2165 	int fd;
2166 	sbd_lu_props_t *sbdProps;
2167 	int ioctlRet;
2168 	int savedErrno;
2169 	int sbdPropsSize = sizeof (*sbdProps) + MAX_SBD_PROPS;
2170 	stmf_iocdata_t sbdIoctl = {0};
2171 
2172 	/*
2173 	 * Open control node for sbd
2174 	 */
2175 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
2176 		return (ret);
2177 
2178 
2179 	*hdl = calloc(1, sizeof (luResourceImpl));
2180 	if (*hdl == NULL) {
2181 		(void) close(fd);
2182 		return (STMF_ERROR_NOMEM);
2183 	}
2184 
2185 	sbdProps = calloc(1, sbdPropsSize);
2186 	if (sbdProps == NULL) {
2187 		free(*hdl);
2188 		(void) close(fd);
2189 		return (STMF_ERROR_NOMEM);
2190 	}
2191 
2192 	ret = createDiskResource((luResourceImpl *)*hdl);
2193 	if (ret != STMF_STATUS_SUCCESS) {
2194 		free(*hdl);
2195 		free(sbdProps);
2196 		(void) close(fd);
2197 		return (ret);
2198 	}
2199 
2200 	sbdProps->slp_input_guid = 1;
2201 	bcopy(luGuid, sbdProps->slp_guid, sizeof (sbdProps->slp_guid));
2202 
2203 	sbdIoctl.stmf_version = STMF_VERSION_1;
2204 	sbdIoctl.stmf_ibuf_size = sbdPropsSize;
2205 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdProps;
2206 	sbdIoctl.stmf_obuf_size = sbdPropsSize;
2207 	sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdProps;
2208 	ioctlRet = ioctl(fd, SBD_IOCTL_GET_LU_PROPS, &sbdIoctl);
2209 	if (ioctlRet != 0) {
2210 		savedErrno = errno;
2211 		switch (savedErrno) {
2212 			case EBUSY:
2213 				ret = STMF_ERROR_BUSY;
2214 				break;
2215 			case EPERM:
2216 			case EACCES:
2217 				ret = STMF_ERROR_PERM;
2218 				break;
2219 			case ENOENT:
2220 				ret = STMF_ERROR_NOT_FOUND;
2221 				break;
2222 			default:
2223 				syslog(LOG_DEBUG,
2224 				    "getDiskAllProps:ioctl error(%d) (%d) (%d)",
2225 				    ioctlRet, sbdIoctl.stmf_error, savedErrno);
2226 				ret = STMF_STATUS_ERROR;
2227 				break;
2228 		}
2229 	}
2230 
2231 	if (ret == STMF_STATUS_SUCCESS) {
2232 		ret = loadDiskPropsFromDriver((luResourceImpl *)*hdl, sbdProps);
2233 	}
2234 
2235 	free(sbdProps);
2236 	(void) close(fd);
2237 	return (ret);
2238 }
2239 
2240 /*
2241  * loadDiskPropsFromDriver
2242  *
2243  * Purpose: Retrieve all disk type properties from sbd driver
2244  *
2245  * hdl - Allocated luResourceImpl
2246  * sbdProps - sbd_lu_props_t structure returned from sbd driver
2247  *
2248  */
2249 static int
2250 loadDiskPropsFromDriver(luResourceImpl *hdl, sbd_lu_props_t *sbdProps)
2251 {
2252 	int ret = STMF_STATUS_SUCCESS;
2253 	diskResource *diskLu = hdl->resource;
2254 	/* copy guid */
2255 	diskLu->luGuidValid = B_TRUE;
2256 	bcopy(sbdProps->slp_guid, diskLu->luGuid, sizeof (sbdProps->slp_guid));
2257 
2258 	if (sbdProps->slp_separate_meta && sbdProps->slp_meta_fname_valid) {
2259 		diskLu->luMetaFileNameValid = B_TRUE;
2260 		if (strlcpy(diskLu->luMetaFileName,
2261 		    (char *)&(sbdProps->slp_buf[sbdProps->slp_meta_fname_off]),
2262 		    sizeof (diskLu->luMetaFileName)) >=
2263 		    sizeof (diskLu->luMetaFileName)) {
2264 			return (STMF_STATUS_ERROR);
2265 		}
2266 	}
2267 
2268 	if (sbdProps->slp_data_fname_valid) {
2269 		diskLu->luDataFileNameValid = B_TRUE;
2270 		if (strlcpy(diskLu->luDataFileName,
2271 		    (char *)&(sbdProps->slp_buf[sbdProps->slp_data_fname_off]),
2272 		    sizeof (diskLu->luDataFileName)) >=
2273 		    sizeof (diskLu->luDataFileName)) {
2274 			return (STMF_STATUS_ERROR);
2275 		}
2276 	}
2277 
2278 	if (sbdProps->slp_serial_valid) {
2279 		diskLu->serialNumValid = B_TRUE;
2280 		bcopy(&(sbdProps->slp_buf[sbdProps->slp_serial_off]),
2281 		    diskLu->serialNum, sbdProps->slp_serial_size);
2282 	}
2283 
2284 	if (sbdProps->slp_mgmt_url_valid) {
2285 		diskLu->luMgmtUrlValid = B_TRUE;
2286 		if (strlcpy(diskLu->luMgmtUrl,
2287 		    (char *)&(sbdProps->slp_buf[sbdProps->slp_mgmt_url_off]),
2288 		    sizeof (diskLu->luMgmtUrl)) >=
2289 		    sizeof (diskLu->luMgmtUrl)) {
2290 			return (STMF_STATUS_ERROR);
2291 		}
2292 	}
2293 
2294 	if (sbdProps->slp_alias_valid) {
2295 		diskLu->luAliasValid = B_TRUE;
2296 		if (strlcpy(diskLu->luAlias,
2297 		    (char *)&(sbdProps->slp_buf[sbdProps->slp_alias_off]),
2298 		    sizeof (diskLu->luAlias)) >=
2299 		    sizeof (diskLu->luAlias)) {
2300 			return (STMF_STATUS_ERROR);
2301 		}
2302 	} else { /* set alias to data filename if not set */
2303 		if (sbdProps->slp_data_fname_valid) {
2304 			diskLu->luAliasValid = B_TRUE;
2305 			if (strlcpy(diskLu->luAlias,
2306 			    (char *)&(sbdProps->slp_buf[
2307 			    sbdProps->slp_data_fname_off]),
2308 			    sizeof (diskLu->luAlias)) >=
2309 			    sizeof (diskLu->luAlias)) {
2310 				return (STMF_STATUS_ERROR);
2311 			}
2312 		}
2313 	}
2314 
2315 	diskLu->vidValid = B_TRUE;
2316 	bcopy(sbdProps->slp_vid, diskLu->vid, sizeof (diskLu->vid));
2317 
2318 	diskLu->pidValid = B_TRUE;
2319 	bcopy(sbdProps->slp_pid, diskLu->pid, sizeof (diskLu->pid));
2320 
2321 	diskLu->revValid = B_TRUE;
2322 	bcopy(sbdProps->slp_rev, diskLu->rev, sizeof (diskLu->rev));
2323 
2324 	diskLu->writeProtectEnableValid = B_TRUE;
2325 	if (sbdProps->slp_write_protected) {
2326 		diskLu->writeProtectEnable = B_TRUE;
2327 	}
2328 
2329 	diskLu->writebackCacheDisableValid = B_TRUE;
2330 	if (sbdProps->slp_writeback_cache_disable_cur) {
2331 		diskLu->writebackCacheDisable = B_TRUE;
2332 	}
2333 
2334 	diskLu->blkSizeValid = B_TRUE;
2335 	diskLu->blkSize = sbdProps->slp_blksize;
2336 
2337 	diskLu->luSizeValid = B_TRUE;
2338 	diskLu->luSize = sbdProps->slp_lu_size;
2339 
2340 	diskLu->accessState = sbdProps->slp_access_state;
2341 
2342 	return (ret);
2343 }
2344 
2345 
2346 /*
2347  * stmfSetLuProp
2348  *
2349  * Purpose: set a property on an luResource
2350  *
2351  * hdl - allocated luResource
2352  * prop - property identifier
2353  * propVal - property value to be set
2354  */
2355 int
2356 stmfSetLuProp(luResource hdl, uint32_t prop, const char *propVal)
2357 {
2358 	int ret = STMF_STATUS_SUCCESS;
2359 	luResourceImpl *luPropsHdl = hdl;
2360 	if (hdl == NULL) {
2361 		return (STMF_ERROR_INVALID_ARG);
2362 	}
2363 
2364 	if (luPropsHdl->type == STMF_DISK) {
2365 		ret = setDiskProp(luPropsHdl, prop, propVal);
2366 	} else {
2367 		return (STMF_ERROR_INVALID_ARG);
2368 	}
2369 
2370 	return (ret);
2371 }
2372 
2373 /*
2374  * getDiskProp
2375  *
2376  * Purpose: retrieve a given property from a logical unit resource of type disk
2377  *
2378  * hdl - allocated luResourceImpl
2379  * prop - property identifier
2380  * propVal - pointer to character to contain the retrieved property value
2381  * propLen - On input this is the length of propVal. On failure, it contains the
2382  *           number of bytes required for propVal
2383  */
2384 static int
2385 getDiskProp(luResourceImpl *hdl, uint32_t prop, char *propVal, size_t *propLen)
2386 {
2387 	int ret = STMF_STATUS_SUCCESS;
2388 	diskResource *diskLu = hdl->resource;
2389 	char accessState[20];
2390 	size_t reqLen;
2391 
2392 	if (prop == STMF_LU_PROP_ACCESS_STATE) {
2393 		if (diskLu->accessState == SBD_LU_ACTIVE) {
2394 			(void) strlcpy(accessState, STMF_ACCESS_ACTIVE,
2395 			    sizeof (accessState));
2396 		} else if (diskLu->accessState == SBD_LU_TRANSITION_TO_ACTIVE) {
2397 			(void) strlcpy(accessState,
2398 			    STMF_ACCESS_STANDBY_TO_ACTIVE,
2399 			    sizeof (accessState));
2400 		} else if (diskLu->accessState == SBD_LU_STANDBY) {
2401 			(void) strlcpy(accessState, STMF_ACCESS_STANDBY,
2402 			    sizeof (accessState));
2403 		} else if (diskLu->accessState ==
2404 		    SBD_LU_TRANSITION_TO_STANDBY) {
2405 			(void) strlcpy(accessState,
2406 			    STMF_ACCESS_ACTIVE_TO_STANDBY,
2407 			    sizeof (accessState));
2408 		}
2409 		if ((reqLen = strlcpy(propVal, accessState,
2410 		    *propLen)) >= *propLen) {
2411 			*propLen = reqLen + 1;
2412 			return (STMF_ERROR_INVALID_ARG);
2413 		}
2414 		return (0);
2415 	}
2416 
2417 	if (diskLu->accessState != SBD_LU_ACTIVE) {
2418 		return (STMF_ERROR_NO_PROP_STANDBY);
2419 	}
2420 
2421 	switch (prop) {
2422 		case STMF_LU_PROP_BLOCK_SIZE:
2423 			if (diskLu->blkSizeValid == B_FALSE) {
2424 				return (STMF_ERROR_NO_PROP);
2425 			}
2426 			reqLen = snprintf(propVal, *propLen, "%llu",
2427 			    (u_longlong_t)diskLu->blkSize);
2428 			if (reqLen >= *propLen) {
2429 				*propLen = reqLen + 1;
2430 				return (STMF_ERROR_INVALID_ARG);
2431 			}
2432 			break;
2433 		case STMF_LU_PROP_FILENAME:
2434 			if (diskLu->luDataFileNameValid == B_FALSE) {
2435 				return (STMF_ERROR_NO_PROP);
2436 			}
2437 			if ((reqLen = strlcpy(propVal, diskLu->luDataFileName,
2438 			    *propLen)) >= *propLen) {
2439 				*propLen = reqLen + 1;
2440 				return (STMF_ERROR_INVALID_ARG);
2441 			}
2442 			break;
2443 		case STMF_LU_PROP_META_FILENAME:
2444 			if (diskLu->luMetaFileNameValid == B_FALSE) {
2445 				return (STMF_ERROR_NO_PROP);
2446 			}
2447 			if ((reqLen = strlcpy(propVal, diskLu->luMetaFileName,
2448 			    *propLen)) >= *propLen) {
2449 				*propLen = reqLen + 1;
2450 				return (STMF_ERROR_INVALID_ARG);
2451 			}
2452 			break;
2453 		case STMF_LU_PROP_MGMT_URL:
2454 			if (diskLu->luMgmtUrlValid == B_FALSE) {
2455 				return (STMF_ERROR_NO_PROP);
2456 			}
2457 			if ((reqLen = strlcpy(propVal, diskLu->luMgmtUrl,
2458 			    *propLen)) >= *propLen) {
2459 				*propLen = reqLen + 1;
2460 				return (STMF_ERROR_INVALID_ARG);
2461 			}
2462 			break;
2463 		case STMF_LU_PROP_GUID:
2464 			if (diskLu->luGuidValid == B_FALSE) {
2465 				return (STMF_ERROR_NO_PROP);
2466 			}
2467 			reqLen = snprintf(propVal, *propLen,
2468 			    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X"
2469 			    "%02X%02X%02X%02X",
2470 			    diskLu->luGuid[0], diskLu->luGuid[1],
2471 			    diskLu->luGuid[2], diskLu->luGuid[3],
2472 			    diskLu->luGuid[4], diskLu->luGuid[5],
2473 			    diskLu->luGuid[6], diskLu->luGuid[7],
2474 			    diskLu->luGuid[8], diskLu->luGuid[9],
2475 			    diskLu->luGuid[10], diskLu->luGuid[11],
2476 			    diskLu->luGuid[12], diskLu->luGuid[13],
2477 			    diskLu->luGuid[14], diskLu->luGuid[15]);
2478 			if (reqLen >= *propLen) {
2479 				*propLen = reqLen + 1;
2480 				return (STMF_ERROR_INVALID_ARG);
2481 			}
2482 			break;
2483 		case STMF_LU_PROP_SERIAL_NUM:
2484 			if (diskLu->serialNumValid == B_FALSE) {
2485 				return (STMF_ERROR_NO_PROP);
2486 			}
2487 			if ((reqLen = strlcpy(propVal, diskLu->serialNum,
2488 			    *propLen)) >= *propLen) {
2489 				*propLen = reqLen + 1;
2490 				return (STMF_ERROR_INVALID_ARG);
2491 			}
2492 			break;
2493 		case STMF_LU_PROP_SIZE:
2494 			if (diskLu->luSizeValid == B_FALSE) {
2495 				return (STMF_ERROR_NO_PROP);
2496 			}
2497 			(void) snprintf(propVal, *propLen, "%llu",
2498 			    (u_longlong_t)diskLu->luSize);
2499 			break;
2500 		case STMF_LU_PROP_ALIAS:
2501 			if (diskLu->luAliasValid == B_FALSE) {
2502 				return (STMF_ERROR_NO_PROP);
2503 			}
2504 			if ((reqLen = strlcpy(propVal, diskLu->luAlias,
2505 			    *propLen)) >= *propLen) {
2506 				*propLen = reqLen + 1;
2507 				return (STMF_ERROR_INVALID_ARG);
2508 			}
2509 			break;
2510 		case STMF_LU_PROP_VID:
2511 			if (diskLu->vidValid == B_FALSE) {
2512 				return (STMF_ERROR_NO_PROP);
2513 			}
2514 			if (*propLen <= sizeof (diskLu->vid)) {
2515 				return (STMF_ERROR_INVALID_ARG);
2516 			}
2517 			bcopy(diskLu->vid, propVal, sizeof (diskLu->vid));
2518 			propVal[sizeof (diskLu->vid)] = 0;
2519 			break;
2520 		case STMF_LU_PROP_PID:
2521 			if (diskLu->pidValid == B_FALSE) {
2522 				return (STMF_ERROR_NO_PROP);
2523 			}
2524 			if (*propLen <= sizeof (diskLu->pid)) {
2525 				return (STMF_ERROR_INVALID_ARG);
2526 			}
2527 			bcopy(diskLu->pid, propVal, sizeof (diskLu->pid));
2528 			propVal[sizeof (diskLu->pid)] = 0;
2529 			break;
2530 		case STMF_LU_PROP_WRITE_PROTECT:
2531 			if (diskLu->writeProtectEnableValid == B_FALSE) {
2532 				return (STMF_ERROR_NO_PROP);
2533 			}
2534 			if (diskLu->writeProtectEnable) {
2535 				if ((reqLen = strlcpy(propVal, "true",
2536 				    *propLen)) >= *propLen) {
2537 					*propLen = reqLen + 1;
2538 					return (STMF_ERROR_INVALID_ARG);
2539 				}
2540 			} else {
2541 				if ((reqLen = strlcpy(propVal, "false",
2542 				    *propLen)) >= *propLen) {
2543 					*propLen = reqLen + 1;
2544 					return (STMF_ERROR_INVALID_ARG);
2545 				}
2546 			}
2547 			break;
2548 		case STMF_LU_PROP_WRITE_CACHE_DISABLE:
2549 			if (diskLu->writebackCacheDisableValid == B_FALSE) {
2550 				return (STMF_ERROR_NO_PROP);
2551 			}
2552 			if (diskLu->writebackCacheDisable) {
2553 				if ((reqLen = strlcpy(propVal, "true",
2554 				    *propLen)) >= *propLen) {
2555 					*propLen = reqLen + 1;
2556 					return (STMF_ERROR_INVALID_ARG);
2557 				}
2558 			} else {
2559 				if ((reqLen = strlcpy(propVal, "false",
2560 				    *propLen)) >= *propLen) {
2561 					*propLen = reqLen + 1;
2562 					return (STMF_ERROR_INVALID_ARG);
2563 				}
2564 			}
2565 			break;
2566 		default:
2567 			ret = STMF_ERROR_NO_PROP;
2568 			break;
2569 	}
2570 
2571 	return (ret);
2572 }
2573 
2574 /*
2575  * setDiskProp
2576  *
2577  * Purpose: set properties for resource of type disk
2578  *
2579  * hdl - allocated luResourceImpl
2580  * resourceProp - valid resource identifier
2581  * propVal - valid resource value
2582  */
2583 static int
2584 setDiskProp(luResourceImpl *hdl, uint32_t resourceProp, const char *propVal)
2585 {
2586 	int ret = STMF_STATUS_SUCCESS;
2587 	int i;
2588 	diskResource *diskLu = hdl->resource;
2589 	unsigned long long numericProp = 0;
2590 	char guidProp[LU_ASCII_GUID_SIZE + 1];
2591 	char ouiProp[OUI_ASCII_SIZE + 1];
2592 	unsigned int oui[OUI_SIZE];
2593 	unsigned int guid[LU_GUID_SIZE];
2594 	int propSize;
2595 
2596 
2597 	if (propVal == NULL) {
2598 		return (STMF_ERROR_INVALID_ARG);
2599 	}
2600 
2601 	switch (resourceProp) {
2602 		case STMF_LU_PROP_ALIAS:
2603 			if (strlcpy(diskLu->luAlias, propVal,
2604 			    sizeof (diskLu->luAlias)) >=
2605 			    sizeof (diskLu->luAlias)) {
2606 				return (STMF_ERROR_INVALID_PROPSIZE);
2607 			}
2608 			diskLu->luAliasValid = B_TRUE;
2609 			break;
2610 		case STMF_LU_PROP_BLOCK_SIZE:
2611 			(void) sscanf(propVal, "%llu", &numericProp);
2612 			if (numericProp > UINT16_MAX) {
2613 				return (STMF_ERROR_INVALID_PROPSIZE);
2614 			}
2615 			diskLu->blkSize = numericProp;
2616 			diskLu->blkSizeValid = B_TRUE;
2617 			break;
2618 		case STMF_LU_PROP_COMPANY_ID:
2619 			if ((strlcpy(ouiProp, propVal, sizeof (ouiProp))) >=
2620 			    sizeof (ouiProp)) {
2621 				return (STMF_ERROR_INVALID_ARG);
2622 			}
2623 			if (checkHexUpper(ouiProp) != 0) {
2624 				return (STMF_ERROR_INVALID_ARG);
2625 			}
2626 			(void) sscanf(ouiProp, "%2X%2X%2X",
2627 			    &oui[0], &oui[1], &oui[2]);
2628 
2629 			diskLu->companyId = 0;
2630 			diskLu->companyId += oui[0] << 16;
2631 			diskLu->companyId += oui[1] << 8;
2632 			diskLu->companyId += oui[2];
2633 			diskLu->companyIdValid = B_TRUE;
2634 			break;
2635 		case STMF_LU_PROP_GUID:
2636 			if (strlen(propVal) != LU_ASCII_GUID_SIZE) {
2637 				return (STMF_ERROR_INVALID_PROPSIZE);
2638 			}
2639 
2640 			if ((strlcpy(guidProp, propVal, sizeof (guidProp))) >=
2641 			    sizeof (guidProp)) {
2642 				return (STMF_ERROR_INVALID_ARG);
2643 			}
2644 
2645 			if (checkHexUpper(guidProp) != 0) {
2646 				return (STMF_ERROR_INVALID_ARG);
2647 			}
2648 
2649 			(void) sscanf(guidProp,
2650 			    "%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X",
2651 			    &guid[0], &guid[1], &guid[2], &guid[3], &guid[4],
2652 			    &guid[5], &guid[6], &guid[7], &guid[8], &guid[9],
2653 			    &guid[10], &guid[11], &guid[12], &guid[13],
2654 			    &guid[14], &guid[15]);
2655 			for (i = 0; i < sizeof (diskLu->luGuid); i++) {
2656 				diskLu->luGuid[i] = guid[i];
2657 			}
2658 			diskLu->luGuidValid = B_TRUE;
2659 			break;
2660 		case STMF_LU_PROP_FILENAME:
2661 			if ((strlcpy(diskLu->luDataFileName, propVal,
2662 			    sizeof (diskLu->luDataFileName))) >=
2663 			    sizeof (diskLu->luDataFileName)) {
2664 				return (STMF_ERROR_INVALID_PROPSIZE);
2665 			}
2666 			diskLu->luDataFileNameValid = B_TRUE;
2667 			break;
2668 		case STMF_LU_PROP_META_FILENAME:
2669 			if ((strlcpy(diskLu->luMetaFileName, propVal,
2670 			    sizeof (diskLu->luMetaFileName))) >=
2671 			    sizeof (diskLu->luMetaFileName)) {
2672 				return (STMF_ERROR_INVALID_PROPSIZE);
2673 			}
2674 			diskLu->luMetaFileNameValid = B_TRUE;
2675 			break;
2676 		case STMF_LU_PROP_MGMT_URL:
2677 			if ((strlcpy(diskLu->luMgmtUrl, propVal,
2678 			    sizeof (diskLu->luMgmtUrl))) >=
2679 			    sizeof (diskLu->luMgmtUrl)) {
2680 				return (STMF_ERROR_INVALID_PROPSIZE);
2681 			}
2682 			diskLu->luMgmtUrlValid = B_TRUE;
2683 			break;
2684 		case STMF_LU_PROP_PID:
2685 			if ((propSize = strlen(propVal)) >
2686 			    sizeof (diskLu->pid)) {
2687 				return (STMF_ERROR_INVALID_PROPSIZE);
2688 			}
2689 			(void) strncpy(diskLu->pid, propVal, propSize);
2690 			diskLu->pidValid = B_TRUE;
2691 			break;
2692 		case STMF_LU_PROP_SERIAL_NUM:
2693 			if ((propSize = strlen(propVal)) >
2694 			    (sizeof (diskLu->serialNum) - 1)) {
2695 				return (STMF_ERROR_INVALID_PROPSIZE);
2696 			}
2697 			(void) strncpy(diskLu->serialNum, propVal, propSize);
2698 			diskLu->serialNumValid = B_TRUE;
2699 			break;
2700 		case STMF_LU_PROP_SIZE:
2701 			if ((niceStrToNum(propVal, &diskLu->luSize) != 0)) {
2702 				return (STMF_ERROR_INVALID_ARG);
2703 			}
2704 			diskLu->luSizeValid = B_TRUE;
2705 			break;
2706 		case STMF_LU_PROP_VID:
2707 			if ((propSize = strlen(propVal)) >
2708 			    sizeof (diskLu->vid)) {
2709 				return (STMF_ERROR_INVALID_PROPSIZE);
2710 			}
2711 			(void) strncpy(diskLu->vid, propVal, propSize);
2712 			diskLu->vidValid = B_TRUE;
2713 			break;
2714 		case STMF_LU_PROP_WRITE_PROTECT:
2715 			if (strcasecmp(propVal, "TRUE") == 0) {
2716 				diskLu->writeProtectEnable = B_TRUE;
2717 			} else if (strcasecmp(propVal, "FALSE") == 0) {
2718 				diskLu->writeProtectEnable = B_FALSE;
2719 			} else {
2720 				return (STMF_ERROR_INVALID_ARG);
2721 			}
2722 			diskLu->writeProtectEnableValid = B_TRUE;
2723 			break;
2724 		case STMF_LU_PROP_WRITE_CACHE_DISABLE:
2725 			if (strcasecmp(propVal, "TRUE") == 0) {
2726 				diskLu->writebackCacheDisable = B_TRUE;
2727 			} else if (strcasecmp(propVal, "FALSE") == 0) {
2728 				diskLu->writebackCacheDisable = B_FALSE;
2729 			} else {
2730 				return (STMF_ERROR_INVALID_ARG);
2731 			}
2732 			diskLu->writebackCacheDisableValid = B_TRUE;
2733 			break;
2734 		case STMF_LU_PROP_ACCESS_STATE:
2735 			ret = STMF_ERROR_INVALID_PROP;
2736 			break;
2737 		default:
2738 			ret = STMF_ERROR_NO_PROP;
2739 			break;
2740 	}
2741 	return (ret);
2742 }
2743 
2744 static int
2745 checkHexUpper(char *buf)
2746 {
2747 	int i;
2748 
2749 	for (i = 0; i < strlen(buf); i++) {
2750 		if (isxdigit(buf[i])) {
2751 			buf[i] = toupper(buf[i]);
2752 			continue;
2753 		}
2754 		return (-1);
2755 	}
2756 
2757 	return (0);
2758 }
2759 
2760 /*
2761  * Given a numeric suffix, convert the value into a number of bits that the
2762  * resulting value must be shifted.
2763  * Code lifted from libzfs_util.c
2764  */
2765 static int
2766 strToShift(const char *buf)
2767 {
2768 	const char *ends = "BKMGTPE";
2769 	int i;
2770 
2771 	if (buf[0] == '\0')
2772 		return (0);
2773 
2774 	for (i = 0; i < strlen(ends); i++) {
2775 		if (toupper(buf[0]) == ends[i])
2776 			return (10*i);
2777 	}
2778 
2779 	return (-1);
2780 }
2781 
2782 int
2783 stmfFreeLuResource(luResource hdl)
2784 {
2785 	int ret = STMF_STATUS_SUCCESS;
2786 	if (hdl == NULL) {
2787 		return (STMF_ERROR_INVALID_ARG);
2788 	}
2789 
2790 	luResourceImpl *hdlImpl = hdl;
2791 	free(hdlImpl->resource);
2792 	free(hdlImpl);
2793 	return (ret);
2794 }
2795 
2796 /*
2797  * Convert a string of the form '100G' into a real number. Used when setting
2798  * the size of a logical unit.
2799  * Code lifted from libzfs_util.c
2800  */
2801 static int
2802 niceStrToNum(const char *value, uint64_t *num)
2803 {
2804 	char *end;
2805 	int shift;
2806 
2807 	*num = 0;
2808 
2809 	/* Check to see if this looks like a number.  */
2810 	if ((value[0] < '0' || value[0] > '9') && value[0] != '.') {
2811 		return (-1);
2812 	}
2813 
2814 	/* Rely on stroull() to process the numeric portion.  */
2815 	errno = 0;
2816 	*num = strtoull(value, &end, 10);
2817 
2818 	/*
2819 	 * Check for ERANGE, which indicates that the value is too large to fit
2820 	 * in a 64-bit value.
2821 	 */
2822 	if (errno == ERANGE) {
2823 		return (-1);
2824 	}
2825 
2826 	/*
2827 	 * If we have a decimal value, then do the computation with floating
2828 	 * point arithmetic.  Otherwise, use standard arithmetic.
2829 	 */
2830 	if (*end == '.') {
2831 		double fval = strtod(value, &end);
2832 
2833 		if ((shift = strToShift(end)) == -1) {
2834 			return (-1);
2835 		}
2836 
2837 		fval *= pow(2, shift);
2838 
2839 		if (fval > UINT64_MAX) {
2840 			return (-1);
2841 		}
2842 
2843 		*num = (uint64_t)fval;
2844 	} else {
2845 		if ((shift = strToShift(end)) == -1) {
2846 			return (-1);
2847 		}
2848 
2849 		/* Check for overflow */
2850 		if (shift >= 64 || (*num << shift) >> shift != *num) {
2851 			return (-1);
2852 		}
2853 
2854 		*num <<= shift;
2855 	}
2856 
2857 	return (0);
2858 }
2859 
2860 /*
2861  * stmfCreateTargetGroup
2862  *
2863  * Purpose: Create a local port group
2864  *
2865  * targetGroupName - name of local port group to create
2866  */
2867 int
2868 stmfCreateTargetGroup(stmfGroupName *targetGroupName)
2869 {
2870 	int ret;
2871 	int fd;
2872 
2873 	if (targetGroupName == NULL ||
2874 	    (strnlen((char *)targetGroupName, sizeof (stmfGroupName))
2875 	    == sizeof (stmfGroupName))) {
2876 		return (STMF_ERROR_INVALID_ARG);
2877 	}
2878 
2879 	/* Check to ensure service exists */
2880 	if (psCheckService() != STMF_STATUS_SUCCESS) {
2881 		return (STMF_ERROR_SERVICE_NOT_FOUND);
2882 	}
2883 
2884 	/* call init */
2885 	ret = initializeConfig();
2886 	if (ret != STMF_STATUS_SUCCESS) {
2887 		return (ret);
2888 	}
2889 
2890 	/*
2891 	 * Open control node for stmf
2892 	 */
2893 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
2894 		return (ret);
2895 
2896 	/*
2897 	 * Add the group to the driver
2898 	 */
2899 	if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_TARGET_GROUP,
2900 	    targetGroupName)) != STMF_STATUS_SUCCESS) {
2901 		goto done;
2902 	}
2903 
2904 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
2905 		goto done;
2906 	}
2907 
2908 	/*
2909 	 * If the add to the driver was successful, add it to the persistent
2910 	 * store.
2911 	 */
2912 	ret = psCreateTargetGroup((char *)targetGroupName);
2913 	switch (ret) {
2914 		case STMF_PS_SUCCESS:
2915 			ret = STMF_STATUS_SUCCESS;
2916 			break;
2917 		case STMF_PS_ERROR_EXISTS:
2918 			ret = STMF_ERROR_EXISTS;
2919 			break;
2920 		case STMF_PS_ERROR_BUSY:
2921 			ret = STMF_ERROR_BUSY;
2922 			break;
2923 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
2924 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
2925 			break;
2926 		case STMF_PS_ERROR_VERSION_MISMATCH:
2927 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
2928 			break;
2929 		default:
2930 			syslog(LOG_DEBUG,
2931 			    "stmfCreateTargetGroup:psCreateTargetGroup"
2932 			    ":error(%d)", ret);
2933 			ret = STMF_STATUS_ERROR;
2934 			break;
2935 	}
2936 
2937 done:
2938 	(void) close(fd);
2939 	return (ret);
2940 }
2941 
2942 /*
2943  * stmfDeleteHostGroup
2944  *
2945  * Purpose: Delete an initiator or local port group
2946  *
2947  * hostGroupName - group to delete
2948  */
2949 int
2950 stmfDeleteHostGroup(stmfGroupName *hostGroupName)
2951 {
2952 	int ret;
2953 	int fd;
2954 
2955 	if (hostGroupName == NULL) {
2956 		return (STMF_ERROR_INVALID_ARG);
2957 	}
2958 
2959 	/* Check to ensure service exists */
2960 	if (psCheckService() != STMF_STATUS_SUCCESS) {
2961 		return (STMF_ERROR_SERVICE_NOT_FOUND);
2962 	}
2963 
2964 	/* call init */
2965 	ret = initializeConfig();
2966 	if (ret != STMF_STATUS_SUCCESS) {
2967 		return (ret);
2968 	}
2969 
2970 	/*
2971 	 * Open control node for stmf
2972 	 */
2973 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
2974 		return (ret);
2975 
2976 	/*
2977 	 * Remove the group from the driver
2978 	 */
2979 	if ((ret = groupIoctl(fd, STMF_IOCTL_REMOVE_HOST_GROUP,
2980 	    hostGroupName)) != STMF_STATUS_SUCCESS) {
2981 		goto done;
2982 	}
2983 
2984 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
2985 		goto done;
2986 	}
2987 
2988 	/*
2989 	 * If the remove from the driver was successful, remove it from the
2990 	 * persistent store.
2991 	 */
2992 	ret = psDeleteHostGroup((char *)hostGroupName);
2993 	switch (ret) {
2994 		case STMF_PS_SUCCESS:
2995 			ret = STMF_STATUS_SUCCESS;
2996 			break;
2997 		case STMF_PS_ERROR_NOT_FOUND:
2998 			ret = STMF_ERROR_NOT_FOUND;
2999 			break;
3000 		case STMF_PS_ERROR_BUSY:
3001 			ret = STMF_ERROR_BUSY;
3002 			break;
3003 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
3004 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
3005 			break;
3006 		case STMF_PS_ERROR_VERSION_MISMATCH:
3007 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
3008 			break;
3009 		default:
3010 			syslog(LOG_DEBUG,
3011 			    "stmfDeleteHostGroup:psDeleteHostGroup:error(%d)",
3012 			    ret);
3013 			ret = STMF_STATUS_ERROR;
3014 			break;
3015 	}
3016 
3017 done:
3018 	(void) close(fd);
3019 	return (ret);
3020 }
3021 
3022 /*
3023  * stmfDeleteTargetGroup
3024  *
3025  * Purpose: Delete an initiator or local port group
3026  *
3027  * targetGroupName - group to delete
3028  */
3029 int
3030 stmfDeleteTargetGroup(stmfGroupName *targetGroupName)
3031 {
3032 	int ret = STMF_STATUS_SUCCESS;
3033 	int fd;
3034 
3035 	if (targetGroupName == NULL) {
3036 		return (STMF_ERROR_INVALID_ARG);
3037 	}
3038 
3039 	/* Check to ensure service exists */
3040 	if (psCheckService() != STMF_STATUS_SUCCESS) {
3041 		return (STMF_ERROR_SERVICE_NOT_FOUND);
3042 	}
3043 
3044 	/* call init */
3045 	ret = initializeConfig();
3046 	if (ret != STMF_STATUS_SUCCESS) {
3047 		return (ret);
3048 	}
3049 
3050 	/*
3051 	 * Open control node for stmf
3052 	 */
3053 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
3054 		return (ret);
3055 
3056 	/*
3057 	 * Remove the group from the driver
3058 	 */
3059 	if ((ret = groupIoctl(fd, STMF_IOCTL_REMOVE_TARGET_GROUP,
3060 	    targetGroupName)) != STMF_STATUS_SUCCESS) {
3061 		goto done;
3062 	}
3063 
3064 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
3065 		goto done;
3066 	}
3067 
3068 	/*
3069 	 * If the remove from the driver was successful, remove it from the
3070 	 * persistent store.
3071 	 */
3072 	ret = psDeleteTargetGroup((char *)targetGroupName);
3073 	switch (ret) {
3074 		case STMF_PS_SUCCESS:
3075 			ret = STMF_STATUS_SUCCESS;
3076 			break;
3077 		case STMF_PS_ERROR_NOT_FOUND:
3078 			ret = STMF_ERROR_NOT_FOUND;
3079 			break;
3080 		case STMF_PS_ERROR_BUSY:
3081 			ret = STMF_ERROR_BUSY;
3082 			break;
3083 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
3084 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
3085 			break;
3086 		case STMF_PS_ERROR_VERSION_MISMATCH:
3087 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
3088 			break;
3089 		default:
3090 			syslog(LOG_DEBUG,
3091 			    "stmfDeleteTargetGroup:psDeleteTargetGroup"
3092 			    ":error(%d)", ret);
3093 			ret = STMF_STATUS_ERROR;
3094 			break;
3095 	}
3096 
3097 done:
3098 	(void) close(fd);
3099 	return (ret);
3100 }
3101 
3102 /*
3103  * stmfDevidFromIscsiName
3104  *
3105  * Purpose: convert an iSCSI name to an stmf devid
3106  *
3107  * iscsiName - unicode nul terminated utf-8 encoded iSCSI name
3108  * devid - on success, contains the converted iscsi name
3109  */
3110 int
3111 stmfDevidFromIscsiName(char *iscsiName, stmfDevid *devid)
3112 {
3113 	if (devid == NULL || iscsiName == NULL)
3114 		return (STMF_ERROR_INVALID_ARG);
3115 
3116 	bzero(devid, sizeof (stmfDevid));
3117 
3118 	/* Validate size of target */
3119 	if ((devid->identLength = strlen(iscsiName)) > MAX_ISCSI_NAME ||
3120 	    devid->identLength < strlen(EUI) ||
3121 	    devid->identLength < strlen(IQN)) {
3122 		return (STMF_ERROR_INVALID_ARG);
3123 	}
3124 
3125 	if ((strncmp(iscsiName, EUI, strlen(EUI)) != 0) &&
3126 	    strncmp(iscsiName, IQN, strlen(IQN)) != 0) {
3127 		return (STMF_ERROR_INVALID_ARG);
3128 	}
3129 
3130 	/* copy UTF-8 bytes to ident */
3131 	bcopy(iscsiName, devid->ident, devid->identLength);
3132 
3133 	return (STMF_STATUS_SUCCESS);
3134 }
3135 
3136 /*
3137  * stmfDevidFromWwn
3138  *
3139  * Purpose: convert a WWN to an stmf devid
3140  *
3141  * wwn - 8-byte wwn identifier
3142  * devid - on success, contains the converted wwn
3143  */
3144 int
3145 stmfDevidFromWwn(uchar_t *wwn, stmfDevid *devid)
3146 {
3147 	if (wwn == NULL || devid == NULL)
3148 		return (STMF_ERROR_INVALID_ARG);
3149 
3150 	bzero(devid, sizeof (stmfDevid));
3151 
3152 	/* Copy eui prefix */
3153 	(void) bcopy(WWN, devid->ident, strlen(WWN));
3154 
3155 	/* Convert to ASCII uppercase hexadecimal string */
3156 	(void) snprintf((char *)&devid->ident[strlen(WWN)],
3157 	    sizeof (devid->ident), "%02X%02X%02X%02X%02X%02X%02X%02X",
3158 	    wwn[0], wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]);
3159 
3160 	devid->identLength = strlen((char *)devid->ident);
3161 
3162 	return (STMF_STATUS_SUCCESS);
3163 }
3164 
3165 /*
3166  * stmfFreeMemory
3167  *
3168  * Purpose: Free memory allocated by this library
3169  *
3170  * memory - previously allocated pointer of memory managed by library
3171  */
3172 void
3173 stmfFreeMemory(void *memory)
3174 {
3175 	free(memory);
3176 }
3177 
3178 /*
3179  * get host group, target group list from stmf
3180  *
3181  * groupType - HOST_GROUP, TARGET_GROUP
3182  */
3183 static int
3184 groupListIoctl(stmfGroupList **groupList, int groupType)
3185 {
3186 	int ret;
3187 	int fd;
3188 	int ioctlRet;
3189 	int i;
3190 	int cmd;
3191 	stmf_iocdata_t stmfIoctl;
3192 	/* framework group list */
3193 	stmf_group_name_t *iGroupList = NULL;
3194 	uint32_t groupListSize;
3195 
3196 	if (groupList == NULL) {
3197 		return (STMF_ERROR_INVALID_ARG);
3198 	}
3199 
3200 	if (groupType == HOST_GROUP) {
3201 		cmd = STMF_IOCTL_GET_HG_LIST;
3202 	} else if (groupType == TARGET_GROUP) {
3203 		cmd = STMF_IOCTL_GET_TG_LIST;
3204 	} else {
3205 		return (STMF_ERROR_INVALID_ARG);
3206 	}
3207 
3208 	/* call init */
3209 	ret = initializeConfig();
3210 	if (ret != STMF_STATUS_SUCCESS) {
3211 		return (ret);
3212 	}
3213 
3214 	/*
3215 	 * Open control node for stmf
3216 	 */
3217 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
3218 		return (ret);
3219 
3220 	/*
3221 	 * Allocate ioctl input buffer
3222 	 */
3223 	groupListSize = ALLOC_GROUP;
3224 	groupListSize = groupListSize * (sizeof (stmf_group_name_t));
3225 	iGroupList = (stmf_group_name_t *)calloc(1, groupListSize);
3226 	if (iGroupList == NULL) {
3227 		ret = STMF_ERROR_NOMEM;
3228 		goto done;
3229 	}
3230 
3231 	bzero(&stmfIoctl, sizeof (stmfIoctl));
3232 	/*
3233 	 * Issue ioctl to get the group list
3234 	 */
3235 	stmfIoctl.stmf_version = STMF_VERSION_1;
3236 	stmfIoctl.stmf_obuf_size = groupListSize;
3237 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupList;
3238 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
3239 	if (ioctlRet != 0) {
3240 		switch (errno) {
3241 			case EBUSY:
3242 				ret = STMF_ERROR_BUSY;
3243 				break;
3244 			case EPERM:
3245 			case EACCES:
3246 				ret = STMF_ERROR_PERM;
3247 				break;
3248 			default:
3249 				syslog(LOG_DEBUG,
3250 				    "groupListIoctl:ioctl errno(%d)",
3251 				    errno);
3252 				ret = STMF_STATUS_ERROR;
3253 				break;
3254 		}
3255 		goto done;
3256 	}
3257 	/*
3258 	 * Check whether input buffer was large enough
3259 	 */
3260 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_GROUP) {
3261 		groupListSize = stmfIoctl.stmf_obuf_max_nentries *
3262 		    sizeof (stmf_group_name_t);
3263 		iGroupList = realloc(iGroupList, groupListSize);
3264 		if (iGroupList == NULL) {
3265 			ret = STMF_ERROR_NOMEM;
3266 			goto done;
3267 		}
3268 		stmfIoctl.stmf_obuf_size = groupListSize;
3269 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupList;
3270 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
3271 		if (ioctlRet != 0) {
3272 			switch (errno) {
3273 				case EBUSY:
3274 					ret = STMF_ERROR_BUSY;
3275 					break;
3276 				case EPERM:
3277 				case EACCES:
3278 					ret = STMF_ERROR_PERM;
3279 					break;
3280 				default:
3281 					syslog(LOG_DEBUG,
3282 					    "groupListIoctl:ioctl errno(%d)",
3283 					    errno);
3284 					ret = STMF_STATUS_ERROR;
3285 					break;
3286 			}
3287 			goto done;
3288 		}
3289 	}
3290 
3291 	/* allocate and copy to caller's buffer */
3292 	*groupList = (stmfGroupList *)calloc(1, sizeof (stmfGroupList) +
3293 	    sizeof (stmfGroupName) * stmfIoctl.stmf_obuf_nentries);
3294 	if (*groupList == NULL) {
3295 		ret = STMF_ERROR_NOMEM;
3296 		goto done;
3297 	}
3298 	(*groupList)->cnt = stmfIoctl.stmf_obuf_nentries;
3299 	for (i = 0; i < stmfIoctl.stmf_obuf_nentries; i++) {
3300 		bcopy(iGroupList[i].name, (*groupList)->name[i],
3301 		    sizeof (stmfGroupName));
3302 	}
3303 
3304 done:
3305 	free(iGroupList);
3306 	(void) close(fd);
3307 	return (ret);
3308 }
3309 
3310 /*
3311  * get host group members, target group members from stmf
3312  *
3313  * groupProps - allocated on success
3314  *
3315  * groupType - HOST_GROUP, TARGET_GROUP
3316  */
3317 static int
3318 groupMemberListIoctl(stmfGroupName *groupName, stmfGroupProperties **groupProps,
3319     int groupType)
3320 {
3321 	int ret;
3322 	int fd;
3323 	int ioctlRet;
3324 	int i;
3325 	int cmd;
3326 	stmf_iocdata_t stmfIoctl;
3327 	/* framework group list */
3328 	stmf_group_name_t iGroupName;
3329 	stmf_ge_ident_t *iGroupMembers;
3330 	uint32_t groupListSize;
3331 
3332 	if (groupName == NULL) {
3333 		return (STMF_ERROR_INVALID_ARG);
3334 	}
3335 
3336 	if (groupType == HOST_GROUP) {
3337 		cmd = STMF_IOCTL_GET_HG_ENTRIES;
3338 	} else if (groupType == TARGET_GROUP) {
3339 		cmd = STMF_IOCTL_GET_TG_ENTRIES;
3340 	} else {
3341 		return (STMF_ERROR_INVALID_ARG);
3342 	}
3343 
3344 	/* call init */
3345 	ret = initializeConfig();
3346 	if (ret != STMF_STATUS_SUCCESS) {
3347 		return (ret);
3348 	}
3349 
3350 	/*
3351 	 * Open control node for stmf
3352 	 */
3353 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
3354 		return (ret);
3355 
3356 	bzero(&iGroupName, sizeof (iGroupName));
3357 
3358 	bcopy(groupName, &iGroupName.name, strlen((char *)groupName));
3359 
3360 	iGroupName.name_size = strlen((char *)groupName);
3361 
3362 	/*
3363 	 * Allocate ioctl input buffer
3364 	 */
3365 	groupListSize = ALLOC_GRP_MEMBER;
3366 	groupListSize = groupListSize * (sizeof (stmf_ge_ident_t));
3367 	iGroupMembers = (stmf_ge_ident_t *)calloc(1, groupListSize);
3368 	if (iGroupMembers == NULL) {
3369 		ret = STMF_ERROR_NOMEM;
3370 		goto done;
3371 	}
3372 
3373 	bzero(&stmfIoctl, sizeof (stmfIoctl));
3374 	/*
3375 	 * Issue ioctl to get the group list
3376 	 */
3377 	stmfIoctl.stmf_version = STMF_VERSION_1;
3378 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&iGroupName;
3379 	stmfIoctl.stmf_ibuf_size = sizeof (stmf_group_name_t);
3380 	stmfIoctl.stmf_obuf_size = groupListSize;
3381 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupMembers;
3382 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
3383 	if (ioctlRet != 0) {
3384 		switch (errno) {
3385 			case EBUSY:
3386 				ret = STMF_ERROR_BUSY;
3387 				break;
3388 			case EPERM:
3389 			case EACCES:
3390 				ret = STMF_ERROR_PERM;
3391 				break;
3392 			default:
3393 				syslog(LOG_DEBUG,
3394 				    "groupListIoctl:ioctl errno(%d)",
3395 				    errno);
3396 				ret = STMF_STATUS_ERROR;
3397 				break;
3398 		}
3399 		goto done;
3400 	}
3401 	/*
3402 	 * Check whether input buffer was large enough
3403 	 */
3404 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_GRP_MEMBER) {
3405 		groupListSize = stmfIoctl.stmf_obuf_max_nentries *
3406 		    sizeof (stmf_ge_ident_t);
3407 		iGroupMembers = realloc(iGroupMembers, groupListSize);
3408 		if (iGroupMembers == NULL) {
3409 			ret = STMF_ERROR_NOMEM;
3410 			goto done;
3411 		}
3412 		stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&iGroupName;
3413 		stmfIoctl.stmf_ibuf_size = sizeof (stmf_group_name_t);
3414 		stmfIoctl.stmf_obuf_size = groupListSize;
3415 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupMembers;
3416 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
3417 		if (ioctlRet != 0) {
3418 			switch (errno) {
3419 				case EBUSY:
3420 					ret = STMF_ERROR_BUSY;
3421 					break;
3422 				case EPERM:
3423 				case EACCES:
3424 					ret = STMF_ERROR_PERM;
3425 					break;
3426 				default:
3427 					syslog(LOG_DEBUG,
3428 					    "groupListIoctl:ioctl errno(%d)",
3429 					    errno);
3430 					ret = STMF_STATUS_ERROR;
3431 					break;
3432 			}
3433 			goto done;
3434 		}
3435 	}
3436 
3437 	/* allocate and copy to caller's buffer */
3438 	*groupProps = (stmfGroupProperties *)calloc(1,
3439 	    sizeof (stmfGroupProperties) +
3440 	    sizeof (stmfDevid) * stmfIoctl.stmf_obuf_nentries);
3441 	if (*groupProps == NULL) {
3442 		ret = STMF_ERROR_NOMEM;
3443 		goto done;
3444 	}
3445 	(*groupProps)->cnt = stmfIoctl.stmf_obuf_nentries;
3446 	for (i = 0; i < stmfIoctl.stmf_obuf_nentries; i++) {
3447 		(*groupProps)->name[i].identLength =
3448 		    iGroupMembers[i].ident_size;
3449 		bcopy(iGroupMembers[i].ident, (*groupProps)->name[i].ident,
3450 		    iGroupMembers[i].ident_size);
3451 	}
3452 
3453 done:
3454 	free(iGroupMembers);
3455 	(void) close(fd);
3456 	return (ret);
3457 }
3458 
3459 /*
3460  * Purpose: access persistent config data for host groups and target groups
3461  */
3462 static int
3463 iLoadGroupFromPs(stmfGroupList **groupList, int type)
3464 {
3465 	int ret;
3466 
3467 	if (groupList == NULL) {
3468 		return (STMF_ERROR_INVALID_ARG);
3469 	}
3470 
3471 	if (type == HOST_GROUP) {
3472 		ret = psGetHostGroupList(groupList);
3473 	} else if (type == TARGET_GROUP) {
3474 		ret = psGetTargetGroupList(groupList);
3475 	} else {
3476 		return (STMF_ERROR_INVALID_ARG);
3477 	}
3478 	switch (ret) {
3479 		case STMF_PS_SUCCESS:
3480 			ret = STMF_STATUS_SUCCESS;
3481 			break;
3482 		case STMF_PS_ERROR_NOT_FOUND:
3483 			ret = STMF_ERROR_NOT_FOUND;
3484 			break;
3485 		case STMF_PS_ERROR_BUSY:
3486 			ret = STMF_ERROR_BUSY;
3487 			break;
3488 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
3489 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
3490 			break;
3491 		case STMF_PS_ERROR_VERSION_MISMATCH:
3492 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
3493 			break;
3494 		default:
3495 			syslog(LOG_DEBUG,
3496 			    "stmfGetHostGroupList:psGetHostGroupList:error(%d)",
3497 			    ret);
3498 			ret = STMF_STATUS_ERROR;
3499 			break;
3500 	}
3501 
3502 	return (ret);
3503 }
3504 
3505 /*
3506  * stmfGetHostGroupList
3507  *
3508  * Purpose: Retrieves the list of initiator group oids
3509  *
3510  * hostGroupList - pointer to pointer to hostGroupList structure
3511  *                 on success, this contains the host group list.
3512  */
3513 int
3514 stmfGetHostGroupList(stmfGroupList **hostGroupList)
3515 {
3516 	int ret = STMF_STATUS_ERROR;
3517 
3518 	if (hostGroupList == NULL) {
3519 		return (STMF_ERROR_INVALID_ARG);
3520 	}
3521 
3522 	ret = groupListIoctl(hostGroupList, HOST_GROUP);
3523 	return (ret);
3524 }
3525 
3526 
3527 /*
3528  * Purpose: access persistent config data for host groups and target groups
3529  */
3530 static int
3531 iLoadGroupMembersFromPs(stmfGroupName *groupName,
3532     stmfGroupProperties **groupProp, int type)
3533 {
3534 	int ret;
3535 
3536 	if (groupName == NULL) {
3537 		return (STMF_ERROR_INVALID_ARG);
3538 	}
3539 
3540 	if (type == HOST_GROUP) {
3541 		ret = psGetHostGroupMemberList((char *)groupName, groupProp);
3542 	} else if (type == TARGET_GROUP) {
3543 		ret = psGetTargetGroupMemberList((char *)groupName, groupProp);
3544 	} else {
3545 		return (STMF_ERROR_INVALID_ARG);
3546 	}
3547 	switch (ret) {
3548 		case STMF_PS_SUCCESS:
3549 			ret = STMF_STATUS_SUCCESS;
3550 			break;
3551 		case STMF_PS_ERROR_NOT_FOUND:
3552 			ret = STMF_ERROR_NOT_FOUND;
3553 			break;
3554 		case STMF_PS_ERROR_BUSY:
3555 			ret = STMF_ERROR_BUSY;
3556 			break;
3557 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
3558 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
3559 			break;
3560 		case STMF_PS_ERROR_VERSION_MISMATCH:
3561 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
3562 			break;
3563 		default:
3564 			syslog(LOG_DEBUG,
3565 			    "iLoadGroupMembersFromPs:psGetHostGroupList:"
3566 			    "error(%d)", ret);
3567 			ret = STMF_STATUS_ERROR;
3568 			break;
3569 	}
3570 
3571 	return (ret);
3572 }
3573 
3574 /*
3575  * stmfGetHostGroupMembers
3576  *
3577  * Purpose: Retrieves the group properties for a host group
3578  *
3579  * groupName - name of group for which to retrieve host group members.
3580  * groupProp - pointer to pointer to stmfGroupProperties structure
3581  *             on success, this contains the list of group members.
3582  */
3583 int
3584 stmfGetHostGroupMembers(stmfGroupName *groupName,
3585     stmfGroupProperties **groupProp)
3586 {
3587 	int ret;
3588 
3589 	if (groupName == NULL || groupProp == NULL) {
3590 		return (STMF_ERROR_INVALID_ARG);
3591 	}
3592 
3593 	ret = groupMemberListIoctl(groupName, groupProp, HOST_GROUP);
3594 
3595 	return (ret);
3596 }
3597 
3598 /*
3599  * stmfGetProviderData
3600  *
3601  * Purpose: Get provider data list
3602  *
3603  * providerName - name of provider for which to retrieve the data
3604  * nvl - pointer to nvlist_t pointer which will contain the nvlist data
3605  *       retrieved.
3606  * providerType - type of provider for which to retrieve data.
3607  *		    STMF_LU_PROVIDER_TYPE
3608  *		    STMF_PORT_PROVIDER_TYPE
3609  */
3610 int
3611 stmfGetProviderData(char *providerName, nvlist_t **nvl, int providerType)
3612 {
3613 	return (stmfGetProviderDataProt(providerName, nvl, providerType,
3614 	    NULL));
3615 }
3616 
3617 /*
3618  * stmfGetProviderDataProt
3619  *
3620  * Purpose: Get provider data list with token
3621  *
3622  * providerName - name of provider for which to retrieve the data
3623  * nvl - pointer to nvlist_t pointer which will contain the nvlist data
3624  *       retrieved.
3625  * providerType - type of provider for which to retrieve data.
3626  *		    STMF_LU_PROVIDER_TYPE
3627  *		    STMF_PORT_PROVIDER_TYPE
3628  * setToken - Returns the stale data token
3629  */
3630 int
3631 stmfGetProviderDataProt(char *providerName, nvlist_t **nvl, int providerType,
3632     uint64_t *setToken)
3633 {
3634 	int ret;
3635 
3636 	if (providerName == NULL || nvl == NULL) {
3637 		return (STMF_ERROR_INVALID_ARG);
3638 	}
3639 	if (providerType != STMF_LU_PROVIDER_TYPE &&
3640 	    providerType != STMF_PORT_PROVIDER_TYPE) {
3641 		return (STMF_ERROR_INVALID_ARG);
3642 	}
3643 	/* call init */
3644 	ret = initializeConfig();
3645 	if (ret != STMF_STATUS_SUCCESS) {
3646 		return (ret);
3647 	}
3648 	return (getProviderData(providerName, nvl, providerType, setToken));
3649 }
3650 
3651 /*
3652  * stmfGetProviderDataList
3653  *
3654  * Purpose: Get the list of providers currently persisting data
3655  *
3656  * providerList - pointer to pointer to an stmfProviderList structure allocated
3657  *                by the caller. Will contain the list of providers on success.
3658  */
3659 int
3660 stmfGetProviderDataList(stmfProviderList **providerList)
3661 {
3662 	int ret;
3663 
3664 	ret = psGetProviderDataList(providerList);
3665 	switch (ret) {
3666 		case STMF_PS_SUCCESS:
3667 			ret = STMF_STATUS_SUCCESS;
3668 			break;
3669 		case STMF_PS_ERROR_BUSY:
3670 			ret = STMF_ERROR_BUSY;
3671 			break;
3672 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
3673 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
3674 			break;
3675 		case STMF_PS_ERROR_VERSION_MISMATCH:
3676 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
3677 			break;
3678 		default:
3679 			syslog(LOG_DEBUG,
3680 			    "stmfGetProviderDataList:psGetProviderDataList"
3681 			    ":error(%d)", ret);
3682 			ret = STMF_STATUS_ERROR;
3683 			break;
3684 	}
3685 
3686 	return (ret);
3687 }
3688 
3689 
3690 /*
3691  * stmfGetSessionList
3692  *
3693  * Purpose: Retrieves the session list for a target (devid)
3694  *
3695  * devid - devid of target for which to retrieve session information.
3696  * sessionList - pointer to pointer to stmfSessionList structure
3697  *             on success, this contains the list of initiator sessions.
3698  */
3699 int
3700 stmfGetSessionList(stmfDevid *devid, stmfSessionList **sessionList)
3701 {
3702 	int ret = STMF_STATUS_SUCCESS;
3703 	int fd;
3704 	int ioctlRet;
3705 	int cmd = STMF_IOCTL_SESSION_LIST;
3706 	int i;
3707 	stmf_iocdata_t stmfIoctl;
3708 	slist_scsi_session_t *fSessionList, *fSessionListP = NULL;
3709 	uint8_t ident[260];
3710 	uint32_t fSessionListSize;
3711 
3712 	if (sessionList == NULL || devid == NULL) {
3713 		ret = STMF_ERROR_INVALID_ARG;
3714 	}
3715 
3716 	/* call init */
3717 	ret = initializeConfig();
3718 	if (ret != STMF_STATUS_SUCCESS) {
3719 		return (ret);
3720 	}
3721 
3722 	/*
3723 	 * Open control node for stmf
3724 	 */
3725 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
3726 		return (ret);
3727 
3728 	/*
3729 	 * Allocate ioctl input buffer
3730 	 */
3731 	fSessionListSize = ALLOC_SESSION;
3732 	fSessionListSize = fSessionListSize * (sizeof (slist_scsi_session_t));
3733 	fSessionList = (slist_scsi_session_t *)calloc(1, fSessionListSize);
3734 	fSessionListP = fSessionList;
3735 	if (fSessionList == NULL) {
3736 		ret = STMF_ERROR_NOMEM;
3737 		goto done;
3738 	}
3739 
3740 	ident[IDENT_LENGTH_BYTE] = devid->identLength;
3741 	bcopy(&(devid->ident), &ident[IDENT_LENGTH_BYTE + 1],
3742 	    devid->identLength);
3743 
3744 	bzero(&stmfIoctl, sizeof (stmfIoctl));
3745 	/*
3746 	 * Issue ioctl to get the session list
3747 	 */
3748 	stmfIoctl.stmf_version = STMF_VERSION_1;
3749 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ident;
3750 	stmfIoctl.stmf_ibuf_size = sizeof (ident);
3751 	stmfIoctl.stmf_obuf_size = fSessionListSize;
3752 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fSessionList;
3753 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
3754 	if (ioctlRet != 0) {
3755 		switch (errno) {
3756 			case EBUSY:
3757 				ret = STMF_ERROR_BUSY;
3758 				break;
3759 			case EPERM:
3760 			case EACCES:
3761 				ret = STMF_ERROR_PERM;
3762 				break;
3763 			default:
3764 				syslog(LOG_DEBUG,
3765 				    "stmfGetSessionList:ioctl errno(%d)",
3766 				    errno);
3767 				ret = STMF_STATUS_ERROR;
3768 				break;
3769 		}
3770 		goto done;
3771 	}
3772 	/*
3773 	 * Check whether input buffer was large enough
3774 	 */
3775 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_SESSION) {
3776 		fSessionListSize = stmfIoctl.stmf_obuf_max_nentries *
3777 		    sizeof (slist_scsi_session_t);
3778 		fSessionList = realloc(fSessionList, fSessionListSize);
3779 		if (fSessionList == NULL) {
3780 			ret = STMF_ERROR_NOMEM;
3781 			goto done;
3782 		}
3783 		fSessionListP = fSessionList;
3784 		stmfIoctl.stmf_obuf_size = fSessionListSize;
3785 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fSessionList;
3786 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
3787 		if (ioctlRet != 0) {
3788 			switch (errno) {
3789 				case EBUSY:
3790 					ret = STMF_ERROR_BUSY;
3791 					break;
3792 				case EPERM:
3793 				case EACCES:
3794 					ret = STMF_ERROR_PERM;
3795 					break;
3796 				default:
3797 					syslog(LOG_DEBUG,
3798 					    "stmfGetSessionList:ioctl "
3799 					    "errno(%d)", errno);
3800 					ret = STMF_STATUS_ERROR;
3801 					break;
3802 			}
3803 			goto done;
3804 		}
3805 	}
3806 
3807 	/*
3808 	 * allocate caller's buffer with the final size
3809 	 */
3810 	*sessionList = (stmfSessionList *)calloc(1, sizeof (stmfSessionList) +
3811 	    stmfIoctl.stmf_obuf_max_nentries * sizeof (stmfSession));
3812 	if (*sessionList == NULL) {
3813 		ret = STMF_ERROR_NOMEM;
3814 		free(sessionList);
3815 		goto done;
3816 	}
3817 
3818 	(*sessionList)->cnt = stmfIoctl.stmf_obuf_max_nentries;
3819 
3820 	/*
3821 	 * copy session info to caller's buffer
3822 	 */
3823 	for (i = 0; i < (*sessionList)->cnt; i++) {
3824 		(*sessionList)->session[i].initiator.identLength =
3825 		    fSessionList->initiator[IDENT_LENGTH_BYTE];
3826 		bcopy(&(fSessionList->initiator[IDENT_LENGTH_BYTE + 1]),
3827 		    (*sessionList)->session[i].initiator.ident,
3828 		    STMF_IDENT_LENGTH);
3829 		bcopy(&(fSessionList->alias),
3830 		    &((*sessionList)->session[i].alias),
3831 		    sizeof ((*sessionList)->session[i].alias));
3832 		bcopy(&(fSessionList++->creation_time),
3833 		    &((*sessionList)->session[i].creationTime),
3834 		    sizeof (time_t));
3835 	}
3836 done:
3837 	(void) close(fd);
3838 	free(fSessionListP);
3839 	return (ret);
3840 }
3841 
3842 /*
3843  * stmfGetTargetGroupList
3844  *
3845  * Purpose: Retrieves the list of target groups
3846  *
3847  * targetGroupList - pointer to a pointer to an stmfGroupList structure. On
3848  *		     success, it contains the list of target groups.
3849  */
3850 int
3851 stmfGetTargetGroupList(stmfGroupList **targetGroupList)
3852 {
3853 	int ret;
3854 
3855 	if (targetGroupList == NULL) {
3856 		return (STMF_ERROR_INVALID_ARG);
3857 	}
3858 
3859 	ret = groupListIoctl(targetGroupList, TARGET_GROUP);
3860 	return (ret);
3861 }
3862 
3863 /*
3864  * stmfGetTargetGroupMembers
3865  *
3866  * Purpose: Retrieves the group members for a target group
3867  *
3868  * groupName - name of target group for which to retrieve members.
3869  * groupProp - pointer to pointer to stmfGroupProperties structure
3870  *             on success, this contains the list of group members.
3871  */
3872 int
3873 stmfGetTargetGroupMembers(stmfGroupName *groupName,
3874     stmfGroupProperties **groupProp)
3875 {
3876 	int ret;
3877 
3878 	if (groupName == NULL || groupProp == NULL) {
3879 		return (STMF_ERROR_INVALID_ARG);
3880 	}
3881 
3882 	ret = groupMemberListIoctl(groupName, groupProp, TARGET_GROUP);
3883 
3884 	return (ret);
3885 }
3886 
3887 /*
3888  * stmfGetTargetList
3889  *
3890  * Purpose: Retrieves the list of target ports
3891  *
3892  * targetList - pointer to a pointer to an stmfDevidList structure.
3893  *		    On success, it contains the list of local ports (target).
3894  */
3895 int
3896 stmfGetTargetList(stmfDevidList **targetList)
3897 {
3898 	int ret;
3899 	int fd;
3900 	int ioctlRet;
3901 	int i;
3902 	stmf_iocdata_t stmfIoctl;
3903 	/* framework target port list */
3904 	slist_target_port_t *fTargetList, *fTargetListP = NULL;
3905 	uint32_t fTargetListSize;
3906 
3907 	if (targetList == NULL) {
3908 		return (STMF_ERROR_INVALID_ARG);
3909 	}
3910 
3911 	/* call init */
3912 	ret = initializeConfig();
3913 	if (ret != STMF_STATUS_SUCCESS) {
3914 		return (ret);
3915 	}
3916 
3917 	/*
3918 	 * Open control node for stmf
3919 	 */
3920 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
3921 		return (ret);
3922 
3923 	/*
3924 	 * Allocate ioctl input buffer
3925 	 */
3926 	fTargetListSize = ALLOC_TARGET_PORT * sizeof (slist_target_port_t);
3927 	fTargetListP = fTargetList =
3928 	    (slist_target_port_t *)calloc(1, fTargetListSize);
3929 	if (fTargetList == NULL) {
3930 		ret = STMF_ERROR_NOMEM;
3931 		goto done;
3932 	}
3933 
3934 	bzero(&stmfIoctl, sizeof (stmfIoctl));
3935 	/*
3936 	 * Issue ioctl to retrieve target list
3937 	 */
3938 	stmfIoctl.stmf_version = STMF_VERSION_1;
3939 	stmfIoctl.stmf_obuf_size = fTargetListSize;
3940 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fTargetList;
3941 	ioctlRet = ioctl(fd, STMF_IOCTL_TARGET_PORT_LIST, &stmfIoctl);
3942 	if (ioctlRet != 0) {
3943 		switch (errno) {
3944 			case EBUSY:
3945 				ret = STMF_ERROR_BUSY;
3946 				break;
3947 			case EPERM:
3948 			case EACCES:
3949 				ret = STMF_ERROR_PERM;
3950 				break;
3951 			default:
3952 				syslog(LOG_DEBUG,
3953 				    "stmfGetTargetList:ioctl errno(%d)", errno);
3954 				ret = STMF_STATUS_ERROR;
3955 				break;
3956 		}
3957 		goto done;
3958 	}
3959 	/*
3960 	 * Check whether input buffer was large enough
3961 	 */
3962 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_TARGET_PORT) {
3963 		fTargetListSize = stmfIoctl.stmf_obuf_max_nentries *
3964 		    sizeof (slist_target_port_t);
3965 		fTargetListP = fTargetList =
3966 		    realloc(fTargetList, fTargetListSize);
3967 		if (fTargetList == NULL) {
3968 			ret = STMF_ERROR_NOMEM;
3969 			goto done;
3970 		}
3971 		stmfIoctl.stmf_obuf_size = fTargetListSize;
3972 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fTargetList;
3973 		ioctlRet = ioctl(fd, STMF_IOCTL_TARGET_PORT_LIST,
3974 		    &stmfIoctl);
3975 		if (ioctlRet != 0) {
3976 			switch (errno) {
3977 				case EBUSY:
3978 					ret = STMF_ERROR_BUSY;
3979 					break;
3980 				case EPERM:
3981 				case EACCES:
3982 					ret = STMF_ERROR_PERM;
3983 					break;
3984 				default:
3985 					syslog(LOG_DEBUG,
3986 					    "stmfGetTargetList:ioctl errno(%d)",
3987 					    errno);
3988 					ret = STMF_STATUS_ERROR;
3989 					break;
3990 			}
3991 			goto done;
3992 		}
3993 	}
3994 
3995 	*targetList = (stmfDevidList *)calloc(1,
3996 	    stmfIoctl.stmf_obuf_max_nentries * sizeof (stmfDevid) +
3997 	    sizeof (stmfDevidList));
3998 	if (*targetList == NULL) {
3999 		ret = STMF_ERROR_NOMEM;
4000 		goto done;
4001 	}
4002 
4003 	(*targetList)->cnt = stmfIoctl.stmf_obuf_max_nentries;
4004 	for (i = 0; i < stmfIoctl.stmf_obuf_max_nentries; i++, fTargetList++) {
4005 		(*targetList)->devid[i].identLength =
4006 		    fTargetList->target[IDENT_LENGTH_BYTE];
4007 		bcopy(&fTargetList->target[IDENT_LENGTH_BYTE + 1],
4008 		    &(*targetList)->devid[i].ident,
4009 		    fTargetList->target[IDENT_LENGTH_BYTE]);
4010 	}
4011 
4012 done:
4013 	(void) close(fd);
4014 	free(fTargetListP);
4015 	return (ret);
4016 }
4017 
4018 /*
4019  * stmfGetTargetProperties
4020  *
4021  * Purpose:  Retrieves the properties for a logical unit
4022  *
4023  * devid - devid of the target for which to retrieve properties
4024  * targetProps - pointer to an stmfTargetProperties structure.
4025  *		On success, it contains the target properties for
4026  *		the specified devid.
4027  */
4028 int
4029 stmfGetTargetProperties(stmfDevid *devid, stmfTargetProperties *targetProps)
4030 {
4031 	int ret = STMF_STATUS_SUCCESS;
4032 	int fd;
4033 	int ioctlRet;
4034 	stmf_iocdata_t stmfIoctl;
4035 	sioc_target_port_props_t targetProperties;
4036 	scsi_devid_desc_t *scsiDevid;
4037 
4038 	if (devid == NULL || targetProps == NULL) {
4039 		return (STMF_ERROR_INVALID_ARG);
4040 	}
4041 
4042 	/* call init */
4043 	ret = initializeConfig();
4044 	if (ret != STMF_STATUS_SUCCESS) {
4045 		return (ret);
4046 	}
4047 
4048 	/*
4049 	 * Open control node for stmf
4050 	 */
4051 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
4052 		return (ret);
4053 
4054 	targetProperties.tgt_id[IDENT_LENGTH_BYTE] = devid->identLength;
4055 	bcopy(&(devid->ident), &targetProperties.tgt_id[IDENT_LENGTH_BYTE + 1],
4056 	    devid->identLength);
4057 
4058 	bzero(&stmfIoctl, sizeof (stmfIoctl));
4059 	/*
4060 	 * Issue ioctl to add to the host group
4061 	 */
4062 	stmfIoctl.stmf_version = STMF_VERSION_1;
4063 	stmfIoctl.stmf_ibuf_size = sizeof (targetProperties.tgt_id);
4064 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&targetProperties.tgt_id;
4065 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&targetProperties;
4066 	stmfIoctl.stmf_obuf_size = sizeof (targetProperties);
4067 	ioctlRet = ioctl(fd, STMF_IOCTL_GET_TARGET_PORT_PROPERTIES,
4068 	    &stmfIoctl);
4069 	if (ioctlRet != 0) {
4070 		switch (errno) {
4071 			case EBUSY:
4072 				ret = STMF_ERROR_BUSY;
4073 				break;
4074 			case EPERM:
4075 			case EACCES:
4076 				ret = STMF_ERROR_PERM;
4077 				break;
4078 			case ENOENT:
4079 				ret = STMF_ERROR_NOT_FOUND;
4080 				break;
4081 			default:
4082 				syslog(LOG_DEBUG,
4083 				    "stmfGetTargetProperties:ioctl errno(%d)",
4084 				    errno);
4085 				ret = STMF_STATUS_ERROR;
4086 				break;
4087 		}
4088 		goto done;
4089 	}
4090 
4091 	bcopy(targetProperties.tgt_provider_name, targetProps->providerName,
4092 	    sizeof (targetProperties.tgt_provider_name));
4093 	if (targetProperties.tgt_state == STMF_STATE_ONLINE) {
4094 		targetProps->status = STMF_TARGET_PORT_ONLINE;
4095 	} else if (targetProperties.tgt_state == STMF_STATE_OFFLINE) {
4096 		targetProps->status = STMF_TARGET_PORT_OFFLINE;
4097 	} else if (targetProperties.tgt_state == STMF_STATE_ONLINING) {
4098 		targetProps->status = STMF_TARGET_PORT_ONLINING;
4099 	} else if (targetProperties.tgt_state == STMF_STATE_OFFLINING) {
4100 		targetProps->status = STMF_TARGET_PORT_OFFLINING;
4101 	}
4102 	bcopy(targetProperties.tgt_alias, targetProps->alias,
4103 	    sizeof (targetProps->alias));
4104 
4105 	scsiDevid = (scsi_devid_desc_t *)&targetProperties.tgt_id;
4106 	targetProps->protocol = scsiDevid->protocol_id;
4107 
4108 done:
4109 	(void) close(fd);
4110 	return (ret);
4111 }
4112 
4113 /*
4114  * stmfGetLogicalUnitList
4115  *
4116  * Purpose: Retrieves list of logical unit Object IDs
4117  *
4118  * luList - pointer to a pointer to a stmfGuidList structure. On success,
4119  *          it contains the list of logical unit guids.
4120  *
4121  */
4122 int
4123 stmfGetLogicalUnitList(stmfGuidList **luList)
4124 {
4125 	int ret;
4126 	int fd;
4127 	int ioctlRet;
4128 	int cmd = STMF_IOCTL_LU_LIST;
4129 	int i;
4130 	stmf_iocdata_t stmfIoctl;
4131 	slist_lu_t *fLuList;
4132 	uint32_t fLuListSize;
4133 	uint32_t listCnt;
4134 
4135 	if (luList == NULL) {
4136 		return (STMF_ERROR_INVALID_ARG);
4137 	}
4138 
4139 	/* call init */
4140 	ret = initializeConfig();
4141 	if (ret != STMF_STATUS_SUCCESS) {
4142 		return (ret);
4143 	}
4144 
4145 	/*
4146 	 * Open control node for stmf
4147 	 */
4148 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
4149 		return (ret);
4150 
4151 	/*
4152 	 * Allocate ioctl input buffer
4153 	 */
4154 	fLuListSize = ALLOC_LU;
4155 	fLuListSize = fLuListSize * (sizeof (slist_lu_t));
4156 	fLuList = (slist_lu_t *)calloc(1, fLuListSize);
4157 	if (fLuList == NULL) {
4158 		ret = STMF_ERROR_NOMEM;
4159 		goto done;
4160 	}
4161 
4162 	bzero(&stmfIoctl, sizeof (stmfIoctl));
4163 	/*
4164 	 * Issue ioctl to get the LU list
4165 	 */
4166 	stmfIoctl.stmf_version = STMF_VERSION_1;
4167 	stmfIoctl.stmf_obuf_size = fLuListSize;
4168 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fLuList;
4169 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
4170 	if (ioctlRet != 0) {
4171 		switch (errno) {
4172 			case EBUSY:
4173 				ret = STMF_ERROR_BUSY;
4174 				break;
4175 			case EPERM:
4176 			case EACCES:
4177 				ret = STMF_ERROR_PERM;
4178 				break;
4179 			default:
4180 				syslog(LOG_DEBUG,
4181 				    "stmfGetLogicalUnitList:ioctl errno(%d)",
4182 				    errno);
4183 				ret = STMF_STATUS_ERROR;
4184 				break;
4185 		}
4186 		goto done;
4187 	}
4188 	/*
4189 	 * Check whether input buffer was large enough
4190 	 */
4191 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_LU) {
4192 		fLuListSize = stmfIoctl.stmf_obuf_max_nentries *
4193 		    sizeof (slist_lu_t);
4194 		free(fLuList);
4195 		fLuList = (slist_lu_t *)calloc(1, fLuListSize);
4196 		if (fLuList == NULL) {
4197 			ret = STMF_ERROR_NOMEM;
4198 			goto done;
4199 		}
4200 		stmfIoctl.stmf_obuf_size = fLuListSize;
4201 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fLuList;
4202 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
4203 		if (ioctlRet != 0) {
4204 			switch (errno) {
4205 				case EBUSY:
4206 					ret = STMF_ERROR_BUSY;
4207 					break;
4208 				case EPERM:
4209 				case EACCES:
4210 					ret = STMF_ERROR_PERM;
4211 					break;
4212 				default:
4213 					syslog(LOG_DEBUG,
4214 					    "stmfGetLogicalUnitList:"
4215 					    "ioctl errno(%d)", errno);
4216 					ret = STMF_STATUS_ERROR;
4217 					break;
4218 			}
4219 			goto done;
4220 		}
4221 	}
4222 
4223 	if (ret != STMF_STATUS_SUCCESS) {
4224 		goto done;
4225 	}
4226 
4227 	listCnt = stmfIoctl.stmf_obuf_nentries;
4228 
4229 	/*
4230 	 * allocate caller's buffer with the final size
4231 	 */
4232 	*luList = (stmfGuidList *)calloc(1, sizeof (stmfGuidList) +
4233 	    listCnt * sizeof (stmfGuid));
4234 	if (*luList == NULL) {
4235 		ret = STMF_ERROR_NOMEM;
4236 		goto done;
4237 	}
4238 
4239 	(*luList)->cnt = listCnt;
4240 
4241 	/* copy to caller's buffer */
4242 	for (i = 0; i < listCnt; i++) {
4243 		bcopy(&fLuList[i].lu_guid, (*luList)->guid[i].guid,
4244 		    sizeof (stmfGuid));
4245 	}
4246 
4247 	/*
4248 	 * sort the list. This gives a consistent view across gets
4249 	 */
4250 	qsort((void *)&((*luList)->guid[0]), (*luList)->cnt,
4251 	    sizeof (stmfGuid), guidCompare);
4252 
4253 done:
4254 	(void) close(fd);
4255 	/*
4256 	 * free internal buffers
4257 	 */
4258 	free(fLuList);
4259 	return (ret);
4260 }
4261 
4262 /*
4263  * stmfGetLogicalUnitProperties
4264  *
4265  * Purpose:  Retrieves the properties for a logical unit
4266  *
4267  * lu - guid of the logical unit for which to retrieve properties
4268  * stmfLuProps - pointer to an stmfLogicalUnitProperties structure. On success,
4269  *               it contains the logical unit properties for the specified guid.
4270  */
4271 int
4272 stmfGetLogicalUnitProperties(stmfGuid *lu, stmfLogicalUnitProperties *luProps)
4273 {
4274 	int ret = STMF_STATUS_SUCCESS;
4275 	int stmfRet;
4276 	int fd;
4277 	int ioctlRet;
4278 	int cmd = STMF_IOCTL_GET_LU_PROPERTIES;
4279 	stmfViewEntryList *viewEntryList = NULL;
4280 	stmf_iocdata_t stmfIoctl;
4281 	sioc_lu_props_t fLuProps;
4282 
4283 	if (lu == NULL || luProps == NULL) {
4284 		return (STMF_ERROR_INVALID_ARG);
4285 	}
4286 
4287 	bzero(luProps, sizeof (stmfLogicalUnitProperties));
4288 
4289 	/* call init */
4290 	ret = initializeConfig();
4291 	if (ret != STMF_STATUS_SUCCESS) {
4292 		return (ret);
4293 	}
4294 
4295 	/*
4296 	 * Open control node for stmf
4297 	 */
4298 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
4299 		return (ret);
4300 
4301 	bzero(&stmfIoctl, sizeof (stmfIoctl));
4302 	/*
4303 	 * Issue ioctl to add to the host group
4304 	 */
4305 	stmfIoctl.stmf_version = STMF_VERSION_1;
4306 	stmfIoctl.stmf_ibuf_size = sizeof (stmfGuid);
4307 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)lu;
4308 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&fLuProps;
4309 	stmfIoctl.stmf_obuf_size = sizeof (fLuProps);
4310 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
4311 	if (ioctlRet != 0) {
4312 		switch (errno) {
4313 			case EBUSY:
4314 				ret = STMF_ERROR_BUSY;
4315 				break;
4316 			case EPERM:
4317 			case EACCES:
4318 				ret = STMF_ERROR_PERM;
4319 				break;
4320 			case ENOENT:
4321 				stmfRet = stmfGetViewEntryList(lu,
4322 				    &viewEntryList);
4323 				if (stmfRet == STMF_STATUS_SUCCESS) {
4324 					luProps->status =
4325 					    STMF_LOGICAL_UNIT_UNREGISTERED;
4326 					if (viewEntryList->cnt > 0) {
4327 						ret = STMF_STATUS_SUCCESS;
4328 					} else {
4329 						ret = STMF_ERROR_NOT_FOUND;
4330 					}
4331 				} else {
4332 					ret = STMF_ERROR_NOT_FOUND;
4333 				}
4334 				stmfFreeMemory(viewEntryList);
4335 				break;
4336 			default:
4337 				syslog(LOG_DEBUG,
4338 				    "stmfGetLogicalUnit:ioctl errno(%d)",
4339 				    errno);
4340 				ret = STMF_STATUS_ERROR;
4341 				break;
4342 		}
4343 		goto done;
4344 	}
4345 
4346 	bcopy(fLuProps.lu_provider_name, luProps->providerName,
4347 	    sizeof (fLuProps.lu_provider_name));
4348 	if (fLuProps.lu_state == STMF_STATE_ONLINE) {
4349 		luProps->status = STMF_LOGICAL_UNIT_ONLINE;
4350 	} else if (fLuProps.lu_state == STMF_STATE_OFFLINE) {
4351 		luProps->status = STMF_LOGICAL_UNIT_OFFLINE;
4352 	} else if (fLuProps.lu_state == STMF_STATE_ONLINING) {
4353 		luProps->status = STMF_LOGICAL_UNIT_ONLINING;
4354 	} else if (fLuProps.lu_state == STMF_STATE_OFFLINING) {
4355 		luProps->status = STMF_LOGICAL_UNIT_OFFLINING;
4356 	}
4357 	bcopy(fLuProps.lu_alias, luProps->alias, sizeof (luProps->alias));
4358 done:
4359 	(void) close(fd);
4360 	return (ret);
4361 }
4362 
4363 /*
4364  * stmfGetState
4365  *
4366  * Purpose: retrieve the current state of the stmf module
4367  *
4368  * state - pointer to stmfState structure allocated by the caller
4369  *         On success, contains the state of stmf
4370  */
4371 int
4372 stmfGetState(stmfState *state)
4373 {
4374 	int ret;
4375 	stmf_state_desc_t iState;
4376 
4377 	if (state == NULL) {
4378 		return (STMF_ERROR_INVALID_ARG);
4379 	}
4380 
4381 	ret = getStmfState(&iState);
4382 	if (ret != STMF_STATUS_SUCCESS) {
4383 		return (ret);
4384 	}
4385 	switch (iState.state) {
4386 		case STMF_STATE_ONLINE:
4387 			state->operationalState =
4388 			    STMF_SERVICE_STATE_ONLINE;
4389 			break;
4390 		case STMF_STATE_OFFLINE:
4391 			state->operationalState =
4392 			    STMF_SERVICE_STATE_OFFLINE;
4393 			break;
4394 		case STMF_STATE_ONLINING:
4395 			state->operationalState =
4396 			    STMF_SERVICE_STATE_ONLINING;
4397 			break;
4398 		case STMF_STATE_OFFLINING:
4399 			state->operationalState =
4400 			    STMF_SERVICE_STATE_OFFLINING;
4401 			break;
4402 		default:
4403 			state->operationalState =
4404 			    STMF_SERVICE_STATE_UNKNOWN;
4405 			break;
4406 	}
4407 	switch (iState.config_state) {
4408 		case STMF_CONFIG_NONE:
4409 			state->configState = STMF_CONFIG_STATE_NONE;
4410 			break;
4411 		case STMF_CONFIG_INIT:
4412 			state->configState = STMF_CONFIG_STATE_INIT;
4413 			break;
4414 		case STMF_CONFIG_INIT_DONE:
4415 			state->configState =
4416 			    STMF_CONFIG_STATE_INIT_DONE;
4417 			break;
4418 		default:
4419 			state->configState =
4420 			    STMF_CONFIG_STATE_UNKNOWN;
4421 			break;
4422 	}
4423 	return (STMF_STATUS_SUCCESS);
4424 }
4425 
4426 /*
4427  * stmfGetViewEntryList
4428  *
4429  * Purpose: Retrieves the list of view entries for the specified
4430  *          logical unit.
4431  *
4432  * lu - the guid of the logical unit for which to retrieve the view entry list
4433  * viewEntryList - a pointer to a pointer to a stmfViewEntryList structure. On
4434  *                 success, contains the list of view entries.
4435  */
4436 int
4437 stmfGetViewEntryList(stmfGuid *lu, stmfViewEntryList **viewEntryList)
4438 {
4439 	int ret;
4440 	int fd;
4441 	int ioctlRet;
4442 	int cmd = STMF_IOCTL_LU_VE_LIST;
4443 	int i;
4444 	stmf_iocdata_t stmfIoctl;
4445 	stmf_view_op_entry_t *fVeList;
4446 	uint32_t fVeListSize;
4447 	uint32_t listCnt;
4448 
4449 	if (lu == NULL || viewEntryList == NULL) {
4450 		return (STMF_ERROR_INVALID_ARG);
4451 	}
4452 
4453 	/* call init */
4454 	ret = initializeConfig();
4455 	if (ret != STMF_STATUS_SUCCESS) {
4456 		return (ret);
4457 	}
4458 
4459 	/*
4460 	 * Open control node for stmf
4461 	 */
4462 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
4463 		return (ret);
4464 
4465 	/*
4466 	 * Allocate ioctl input buffer
4467 	 */
4468 	fVeListSize = ALLOC_VE;
4469 	fVeListSize = fVeListSize * (sizeof (stmf_view_op_entry_t));
4470 	fVeList = (stmf_view_op_entry_t *)calloc(1, fVeListSize);
4471 	if (fVeList == NULL) {
4472 		ret = STMF_ERROR_NOMEM;
4473 		goto done;
4474 	}
4475 
4476 	bzero(&stmfIoctl, sizeof (stmfIoctl));
4477 	/*
4478 	 * Issue ioctl to get the LU list
4479 	 */
4480 	stmfIoctl.stmf_version = STMF_VERSION_1;
4481 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)lu;
4482 	stmfIoctl.stmf_ibuf_size = sizeof (stmfGuid);
4483 	stmfIoctl.stmf_obuf_size = fVeListSize;
4484 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fVeList;
4485 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
4486 	if (ioctlRet != 0) {
4487 		switch (errno) {
4488 			case EBUSY:
4489 				ret = STMF_ERROR_BUSY;
4490 				break;
4491 			case EPERM:
4492 			case EACCES:
4493 				ret = STMF_ERROR_PERM;
4494 				break;
4495 			default:
4496 				syslog(LOG_DEBUG,
4497 				    "stmfGetViewEntryList:ioctl errno(%d)",
4498 				    errno);
4499 				ret = STMF_STATUS_ERROR;
4500 				break;
4501 		}
4502 		goto done;
4503 	}
4504 	/*
4505 	 * Check whether input buffer was large enough
4506 	 */
4507 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_VE) {
4508 		bzero(&stmfIoctl, sizeof (stmfIoctl));
4509 		fVeListSize = stmfIoctl.stmf_obuf_max_nentries *
4510 		    sizeof (stmf_view_op_entry_t);
4511 		free(fVeList);
4512 		fVeList = (stmf_view_op_entry_t *)calloc(1, fVeListSize);
4513 		if (fVeList == NULL) {
4514 			return (STMF_ERROR_NOMEM);
4515 		}
4516 		stmfIoctl.stmf_obuf_size = fVeListSize;
4517 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fVeList;
4518 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
4519 		if (ioctlRet != 0) {
4520 			switch (errno) {
4521 				case EBUSY:
4522 					ret = STMF_ERROR_BUSY;
4523 					break;
4524 				case EPERM:
4525 				case EACCES:
4526 					ret = STMF_ERROR_PERM;
4527 					break;
4528 				default:
4529 					syslog(LOG_DEBUG,
4530 					    "stmfGetLogicalUnitList:"
4531 					    "ioctl errno(%d)", errno);
4532 					ret = STMF_STATUS_ERROR;
4533 					break;
4534 			}
4535 			goto done;
4536 		}
4537 	}
4538 
4539 	if (ret != STMF_STATUS_SUCCESS) {
4540 		goto done;
4541 	}
4542 
4543 	if (stmfIoctl.stmf_obuf_nentries == 0) {
4544 		ret = STMF_ERROR_NOT_FOUND;
4545 		goto done;
4546 	}
4547 
4548 	listCnt = stmfIoctl.stmf_obuf_nentries;
4549 
4550 	/*
4551 	 * allocate caller's buffer with the final size
4552 	 */
4553 	*viewEntryList = (stmfViewEntryList *)calloc(1,
4554 	    sizeof (stmfViewEntryList) + listCnt * sizeof (stmfViewEntry));
4555 	if (*viewEntryList == NULL) {
4556 		ret = STMF_ERROR_NOMEM;
4557 		goto done;
4558 	}
4559 
4560 	(*viewEntryList)->cnt = listCnt;
4561 
4562 	/* copy to caller's buffer */
4563 	for (i = 0; i < listCnt; i++) {
4564 		(*viewEntryList)->ve[i].veIndexValid = B_TRUE;
4565 		(*viewEntryList)->ve[i].veIndex = fVeList[i].ve_ndx;
4566 		if (fVeList[i].ve_all_hosts == 1) {
4567 			(*viewEntryList)->ve[i].allHosts = B_TRUE;
4568 		} else {
4569 			bcopy(fVeList[i].ve_host_group.name,
4570 			    (*viewEntryList)->ve[i].hostGroup,
4571 			    fVeList[i].ve_host_group.name_size);
4572 		}
4573 		if (fVeList[i].ve_all_targets == 1) {
4574 			(*viewEntryList)->ve[i].allTargets = B_TRUE;
4575 		} else {
4576 			bcopy(fVeList[i].ve_target_group.name,
4577 			    (*viewEntryList)->ve[i].targetGroup,
4578 			    fVeList[i].ve_target_group.name_size);
4579 		}
4580 		bcopy(fVeList[i].ve_lu_nbr, (*viewEntryList)->ve[i].luNbr,
4581 		    sizeof ((*viewEntryList)->ve[i].luNbr));
4582 		(*viewEntryList)->ve[i].luNbrValid = B_TRUE;
4583 	}
4584 
4585 	/*
4586 	 * sort the list. This gives a consistent view across gets
4587 	 */
4588 	qsort((void *)&((*viewEntryList)->ve[0]), (*viewEntryList)->cnt,
4589 	    sizeof (stmfViewEntry), viewEntryCompare);
4590 
4591 done:
4592 	(void) close(fd);
4593 	/*
4594 	 * free internal buffers
4595 	 */
4596 	free(fVeList);
4597 	return (ret);
4598 }
4599 
4600 
4601 /*
4602  * loadHostGroups
4603  *
4604  * Purpose - issues the ioctl to load the host groups into stmf
4605  *
4606  * fd - file descriptor for the control node of stmf.
4607  * groupList - populated host group list
4608  */
4609 static int
4610 loadHostGroups(int fd, stmfGroupList *groupList)
4611 {
4612 	int i, j;
4613 	int ret = STMF_STATUS_SUCCESS;
4614 	stmfGroupProperties *groupProps = NULL;
4615 
4616 	for (i = 0; i < groupList->cnt; i++) {
4617 		if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_HOST_GROUP,
4618 		    &(groupList->name[i]))) != STMF_STATUS_SUCCESS) {
4619 			goto out;
4620 		}
4621 		ret = iLoadGroupMembersFromPs(&(groupList->name[i]),
4622 		    &groupProps, HOST_GROUP);
4623 		for (j = 0; j < groupProps->cnt; j++) {
4624 			if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_HG_ENTRY,
4625 			    &(groupList->name[i]), &(groupProps->name[j])))
4626 			    != STMF_STATUS_SUCCESS) {
4627 				goto out;
4628 			}
4629 		}
4630 	}
4631 
4632 
4633 out:
4634 	stmfFreeMemory(groupProps);
4635 	return (ret);
4636 }
4637 
4638 /*
4639  * loadTargetGroups
4640  *
4641  * Purpose - issues the ioctl to load the target groups into stmf
4642  *
4643  * fd - file descriptor for the control node of stmf.
4644  * groupList - populated target group list.
4645  */
4646 static int
4647 loadTargetGroups(int fd, stmfGroupList *groupList)
4648 {
4649 	int i, j;
4650 	int ret = STMF_STATUS_SUCCESS;
4651 	stmfGroupProperties *groupProps = NULL;
4652 
4653 	for (i = 0; i < groupList->cnt; i++) {
4654 		if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_TARGET_GROUP,
4655 		    &(groupList->name[i]))) != STMF_STATUS_SUCCESS) {
4656 			goto out;
4657 		}
4658 		ret = iLoadGroupMembersFromPs(&(groupList->name[i]),
4659 		    &groupProps, TARGET_GROUP);
4660 		for (j = 0; j < groupProps->cnt; j++) {
4661 			if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_TG_ENTRY,
4662 			    &(groupList->name[i]), &(groupProps->name[j])))
4663 			    != STMF_STATUS_SUCCESS) {
4664 				goto out;
4665 			}
4666 		}
4667 	}
4668 
4669 
4670 out:
4671 	stmfFreeMemory(groupProps);
4672 	return (ret);
4673 }
4674 
4675 
4676 /*
4677  * loadStore
4678  *
4679  * Purpose: Load the configuration data from the store
4680  *
4681  * First load the host groups and target groups, then the view entries
4682  * and finally the provider data
4683  *
4684  * fd - file descriptor of control node for stmf.
4685  */
4686 static int
4687 loadStore(int fd)
4688 {
4689 	int ret;
4690 	int i, j;
4691 	stmfGroupList *groupList = NULL;
4692 	stmfGuidList *guidList = NULL;
4693 	stmfViewEntryList *viewEntryList = NULL;
4694 	stmfProviderList *providerList = NULL;
4695 	int providerType;
4696 	nvlist_t *nvl = NULL;
4697 
4698 
4699 
4700 	/* load host groups */
4701 	ret = iLoadGroupFromPs(&groupList, HOST_GROUP);
4702 	if (ret != STMF_STATUS_SUCCESS) {
4703 		return (ret);
4704 	}
4705 	ret = loadHostGroups(fd, groupList);
4706 	if (ret != STMF_STATUS_SUCCESS) {
4707 		goto out;
4708 	}
4709 
4710 	stmfFreeMemory(groupList);
4711 	groupList = NULL;
4712 
4713 	/* load target groups */
4714 	ret = iLoadGroupFromPs(&groupList, TARGET_GROUP);
4715 	if (ret != STMF_STATUS_SUCCESS) {
4716 		goto out;
4717 	}
4718 	ret = loadTargetGroups(fd, groupList);
4719 	if (ret != STMF_STATUS_SUCCESS) {
4720 		goto out;
4721 	}
4722 
4723 	stmfFreeMemory(groupList);
4724 	groupList = NULL;
4725 
4726 	/* Get the guid list */
4727 	ret = psGetLogicalUnitList(&guidList);
4728 	switch (ret) {
4729 		case STMF_PS_SUCCESS:
4730 			ret = STMF_STATUS_SUCCESS;
4731 			break;
4732 		case STMF_PS_ERROR_NOT_FOUND:
4733 			ret = STMF_ERROR_NOT_FOUND;
4734 			break;
4735 		case STMF_PS_ERROR_BUSY:
4736 			ret = STMF_ERROR_BUSY;
4737 			break;
4738 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
4739 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
4740 			break;
4741 		case STMF_PS_ERROR_VERSION_MISMATCH:
4742 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
4743 			break;
4744 		default:
4745 			ret = STMF_STATUS_ERROR;
4746 			break;
4747 	}
4748 
4749 	if (ret != STMF_STATUS_SUCCESS) {
4750 		goto out;
4751 	}
4752 
4753 	/*
4754 	 * We have the guid list, now get the corresponding
4755 	 * view entries for each guid
4756 	 */
4757 	for (i = 0; i < guidList->cnt; i++) {
4758 		ret = psGetViewEntryList(&guidList->guid[i], &viewEntryList);
4759 		switch (ret) {
4760 			case STMF_PS_SUCCESS:
4761 				ret = STMF_STATUS_SUCCESS;
4762 				break;
4763 			case STMF_PS_ERROR_NOT_FOUND:
4764 				ret = STMF_ERROR_NOT_FOUND;
4765 				break;
4766 			case STMF_PS_ERROR_BUSY:
4767 				ret = STMF_ERROR_BUSY;
4768 				break;
4769 			case STMF_PS_ERROR_SERVICE_NOT_FOUND:
4770 				ret = STMF_ERROR_SERVICE_NOT_FOUND;
4771 				break;
4772 			case STMF_PS_ERROR_VERSION_MISMATCH:
4773 				ret = STMF_ERROR_SERVICE_DATA_VERSION;
4774 				break;
4775 			default:
4776 				ret = STMF_STATUS_ERROR;
4777 				break;
4778 		}
4779 		if (ret != STMF_STATUS_SUCCESS) {
4780 			goto out;
4781 		}
4782 		for (j = 0; j < viewEntryList->cnt; j++) {
4783 			ret = addViewEntryIoctl(fd, &guidList->guid[i],
4784 			    &viewEntryList->ve[j]);
4785 			if (ret != STMF_STATUS_SUCCESS) {
4786 				goto out;
4787 			}
4788 		}
4789 	}
4790 
4791 	/* get the list of providers that have data */
4792 	ret = psGetProviderDataList(&providerList);
4793 	switch (ret) {
4794 		case STMF_PS_SUCCESS:
4795 			ret = STMF_STATUS_SUCCESS;
4796 			break;
4797 		case STMF_PS_ERROR_NOT_FOUND:
4798 			ret = STMF_ERROR_NOT_FOUND;
4799 			break;
4800 		case STMF_PS_ERROR_BUSY:
4801 			ret = STMF_ERROR_BUSY;
4802 			break;
4803 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
4804 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
4805 			break;
4806 		case STMF_PS_ERROR_VERSION_MISMATCH:
4807 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
4808 			break;
4809 		default:
4810 			ret = STMF_STATUS_ERROR;
4811 			break;
4812 	}
4813 	if (ret != STMF_STATUS_SUCCESS) {
4814 		goto out;
4815 	}
4816 
4817 	for (i = 0; i < providerList->cnt; i++) {
4818 		providerType = providerList->provider[i].providerType;
4819 		ret = psGetProviderData(providerList->provider[i].name,
4820 		    &nvl, providerType, NULL);
4821 		switch (ret) {
4822 			case STMF_PS_SUCCESS:
4823 				ret = STMF_STATUS_SUCCESS;
4824 				break;
4825 			case STMF_PS_ERROR_NOT_FOUND:
4826 				ret = STMF_ERROR_NOT_FOUND;
4827 				break;
4828 			case STMF_PS_ERROR_BUSY:
4829 				ret = STMF_ERROR_BUSY;
4830 				break;
4831 			case STMF_PS_ERROR_SERVICE_NOT_FOUND:
4832 				ret = STMF_ERROR_SERVICE_NOT_FOUND;
4833 				break;
4834 			case STMF_PS_ERROR_VERSION_MISMATCH:
4835 				ret = STMF_ERROR_SERVICE_DATA_VERSION;
4836 				break;
4837 			default:
4838 				ret = STMF_STATUS_ERROR;
4839 				break;
4840 		}
4841 		if (ret != STMF_STATUS_SUCCESS) {
4842 			goto out;
4843 		}
4844 
4845 		/* call setProviderData */
4846 		ret = setProviderData(fd, providerList->provider[i].name, nvl,
4847 		    providerType, NULL);
4848 		switch (ret) {
4849 			case STMF_PS_SUCCESS:
4850 				ret = STMF_STATUS_SUCCESS;
4851 				break;
4852 			case STMF_PS_ERROR_NOT_FOUND:
4853 				ret = STMF_ERROR_NOT_FOUND;
4854 				break;
4855 			case STMF_PS_ERROR_BUSY:
4856 				ret = STMF_ERROR_BUSY;
4857 				break;
4858 			case STMF_PS_ERROR_SERVICE_NOT_FOUND:
4859 				ret = STMF_ERROR_SERVICE_NOT_FOUND;
4860 				break;
4861 			case STMF_PS_ERROR_VERSION_MISMATCH:
4862 				ret = STMF_ERROR_SERVICE_DATA_VERSION;
4863 				break;
4864 			default:
4865 				ret = STMF_STATUS_ERROR;
4866 				break;
4867 		}
4868 		if (ret != STMF_STATUS_SUCCESS) {
4869 			goto out;
4870 		}
4871 
4872 		nvlist_free(nvl);
4873 		nvl = NULL;
4874 	}
4875 out:
4876 	if (groupList != NULL) {
4877 		free(groupList);
4878 	}
4879 	if (guidList != NULL) {
4880 		free(guidList);
4881 	}
4882 	if (viewEntryList != NULL) {
4883 		free(viewEntryList);
4884 	}
4885 	if (nvl != NULL) {
4886 		nvlist_free(nvl);
4887 	}
4888 	return (ret);
4889 }
4890 
4891 /*
4892  * stmfGetAluaState
4893  *
4894  * Purpose - Get the alua state
4895  *
4896  */
4897 int
4898 stmfGetAluaState(boolean_t *enabled, uint32_t *node)
4899 {
4900 	int ret = STMF_STATUS_SUCCESS;
4901 	int fd;
4902 	stmf_iocdata_t stmfIoctl = {0};
4903 	stmf_alua_state_desc_t alua_state = {0};
4904 	int ioctlRet;
4905 
4906 	if (enabled == NULL || node == NULL) {
4907 		return (STMF_ERROR_INVALID_ARG);
4908 	}
4909 
4910 	/*
4911 	 * Open control node for stmf
4912 	 */
4913 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
4914 		return (ret);
4915 
4916 	/*
4917 	 * Issue ioctl to get the stmf state
4918 	 */
4919 	stmfIoctl.stmf_version = STMF_VERSION_1;
4920 	stmfIoctl.stmf_obuf_size = sizeof (alua_state);
4921 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&alua_state;
4922 	ioctlRet = ioctl(fd, STMF_IOCTL_GET_ALUA_STATE, &stmfIoctl);
4923 
4924 	(void) close(fd);
4925 
4926 	if (ioctlRet != 0) {
4927 		switch (errno) {
4928 			case EBUSY:
4929 				ret = STMF_ERROR_BUSY;
4930 				break;
4931 			case EPERM:
4932 			case EACCES:
4933 				ret = STMF_ERROR_PERM;
4934 				break;
4935 			default:
4936 				syslog(LOG_DEBUG,
4937 				    "getStmfState:ioctl errno(%d)", errno);
4938 				ret = STMF_STATUS_ERROR;
4939 				break;
4940 		}
4941 	} else {
4942 		if (alua_state.alua_state == 1) {
4943 			*enabled = B_TRUE;
4944 		} else {
4945 			*enabled = B_FALSE;
4946 		}
4947 		*node = alua_state.alua_node;
4948 	}
4949 
4950 	return (ret);
4951 }
4952 
4953 /*
4954  * stmfSetAluaState
4955  *
4956  * Purpose - set the alua state to enabled/disabled
4957  *
4958  */
4959 int
4960 stmfSetAluaState(boolean_t enabled, uint32_t node)
4961 {
4962 	int ret = STMF_STATUS_SUCCESS;
4963 	int fd;
4964 	stmf_iocdata_t stmfIoctl = {0};
4965 	stmf_alua_state_desc_t alua_state = {0};
4966 	int ioctlRet;
4967 
4968 	if ((enabled != B_TRUE && enabled != B_FALSE) || (node > 1)) {
4969 		return (STMF_ERROR_INVALID_ARG);
4970 	}
4971 
4972 	if (enabled) {
4973 		alua_state.alua_state = 1;
4974 	}
4975 
4976 	alua_state.alua_node = node;
4977 
4978 	/*
4979 	 * Open control node for stmf
4980 	 */
4981 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
4982 		return (ret);
4983 
4984 	/*
4985 	 * Issue ioctl to get the stmf state
4986 	 */
4987 	stmfIoctl.stmf_version = STMF_VERSION_1;
4988 	stmfIoctl.stmf_ibuf_size = sizeof (alua_state);
4989 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&alua_state;
4990 	ioctlRet = ioctl(fd, STMF_IOCTL_SET_ALUA_STATE, &stmfIoctl);
4991 
4992 	(void) close(fd);
4993 
4994 	if (ioctlRet != 0) {
4995 		switch (errno) {
4996 			case EBUSY:
4997 				ret = STMF_ERROR_BUSY;
4998 				break;
4999 			case EPERM:
5000 			case EACCES:
5001 				ret = STMF_ERROR_PERM;
5002 				break;
5003 			default:
5004 				syslog(LOG_DEBUG,
5005 				    "getStmfState:ioctl errno(%d)", errno);
5006 				ret = STMF_STATUS_ERROR;
5007 				break;
5008 		}
5009 	}
5010 	if (ret == STMF_STATUS_SUCCESS) {
5011 		deleteNonActiveLus();
5012 	}
5013 
5014 	return (ret);
5015 }
5016 
5017 static void
5018 deleteNonActiveLus()
5019 {
5020 	int stmfRet;
5021 	int i;
5022 	stmfGuidList *luList;
5023 	luResource hdl = NULL;
5024 	char propVal[10];
5025 	size_t propValSize = sizeof (propVal);
5026 
5027 	stmfRet = stmfGetLogicalUnitList(&luList);
5028 	if (stmfRet != STMF_STATUS_SUCCESS) {
5029 		return;
5030 	}
5031 
5032 	for (i = 0; i < luList->cnt; i++) {
5033 		stmfRet = stmfGetLuResource(&luList->guid[i], &hdl);
5034 		if (stmfRet != STMF_STATUS_SUCCESS) {
5035 			goto err;
5036 		}
5037 		stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_ACCESS_STATE, propVal,
5038 		    &propValSize);
5039 		if (stmfRet != STMF_STATUS_SUCCESS) {
5040 			goto err;
5041 		}
5042 		if (propVal[0] == '0') {
5043 			(void) stmfFreeLuResource(hdl);
5044 			hdl = NULL;
5045 			continue;
5046 		}
5047 		(void) stmfDeleteLu(&luList->guid[i]);
5048 		(void) stmfFreeLuResource(hdl);
5049 		hdl = NULL;
5050 	}
5051 
5052 err:
5053 	stmfFreeMemory(luList);
5054 	(void) stmfFreeLuResource(hdl);
5055 }
5056 
5057 /*
5058  * stmfLoadConfig
5059  *
5060  * Purpose - load the configuration data from smf into stmf
5061  *
5062  */
5063 int
5064 stmfLoadConfig(void)
5065 {
5066 	int ret = STMF_STATUS_SUCCESS;
5067 	int fd;
5068 	stmf_state_desc_t stmfStateSet;
5069 	stmfState state;
5070 
5071 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
5072 		stmfStateSet.state = STMF_STATE_OFFLINE;
5073 
5074 		if ((ret = openStmf(OPEN_EXCL_STMF, &fd))
5075 		    != STMF_STATUS_SUCCESS) {
5076 			return (ret);
5077 		}
5078 		/*
5079 		 * Configuration not stored persistently; nothing to
5080 		 * initialize so do not set to STMF_CONFIG_INIT.
5081 		 */
5082 		stmfStateSet.config_state = STMF_CONFIG_INIT_DONE;
5083 		goto done;
5084 	}
5085 
5086 	/* Check to ensure service exists */
5087 	if (psCheckService() != STMF_STATUS_SUCCESS) {
5088 		return (STMF_ERROR_SERVICE_NOT_FOUND);
5089 	}
5090 
5091 	ret = stmfGetState(&state);
5092 	if (ret == STMF_STATUS_SUCCESS) {
5093 		if (state.operationalState != STMF_SERVICE_STATE_OFFLINE) {
5094 			return (STMF_ERROR_SERVICE_ONLINE);
5095 		}
5096 	} else {
5097 		return (STMF_STATUS_ERROR);
5098 	}
5099 
5100 
5101 	stmfStateSet.state = STMF_STATE_OFFLINE;
5102 	stmfStateSet.config_state = STMF_CONFIG_INIT;
5103 
5104 	/*
5105 	 * Open control node for stmf
5106 	 */
5107 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
5108 		return (ret);
5109 
5110 	ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE);
5111 	if (ret != STMF_STATUS_SUCCESS) {
5112 		goto done;
5113 	}
5114 
5115 	/* Load the persistent configuration data */
5116 	ret = loadStore(fd);
5117 	if (ret != 0) {
5118 		goto done;
5119 	}
5120 
5121 	stmfStateSet.state = STMF_STATE_OFFLINE;
5122 	stmfStateSet.config_state = STMF_CONFIG_INIT_DONE;
5123 
5124 done:
5125 	if (ret == STMF_STATUS_SUCCESS) {
5126 		ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE);
5127 	}
5128 	(void) close(fd);
5129 	return (ret);
5130 }
5131 
5132 
5133 /*
5134  * getStmfState
5135  *
5136  * stmfState - pointer to stmf_state_desc_t structure. Will contain the state
5137  *             information of the stmf service on success.
5138  */
5139 static int
5140 getStmfState(stmf_state_desc_t *stmfState)
5141 {
5142 	int ret = STMF_STATUS_SUCCESS;
5143 	int fd;
5144 	int ioctlRet;
5145 	stmf_iocdata_t stmfIoctl;
5146 
5147 	/*
5148 	 * Open control node for stmf
5149 	 */
5150 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
5151 		return (ret);
5152 
5153 	bzero(&stmfIoctl, sizeof (stmfIoctl));
5154 	/*
5155 	 * Issue ioctl to get the stmf state
5156 	 */
5157 	stmfIoctl.stmf_version = STMF_VERSION_1;
5158 	stmfIoctl.stmf_ibuf_size = sizeof (stmf_state_desc_t);
5159 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)stmfState;
5160 	stmfIoctl.stmf_obuf_size = sizeof (stmf_state_desc_t);
5161 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)stmfState;
5162 	ioctlRet = ioctl(fd, STMF_IOCTL_GET_STMF_STATE, &stmfIoctl);
5163 
5164 	(void) close(fd);
5165 
5166 	if (ioctlRet != 0) {
5167 		switch (errno) {
5168 			case EBUSY:
5169 				ret = STMF_ERROR_BUSY;
5170 				break;
5171 			case EPERM:
5172 			case EACCES:
5173 				ret = STMF_ERROR_PERM;
5174 				break;
5175 			default:
5176 				syslog(LOG_DEBUG,
5177 				    "getStmfState:ioctl errno(%d)", errno);
5178 				ret = STMF_STATUS_ERROR;
5179 				break;
5180 		}
5181 	}
5182 	return (ret);
5183 }
5184 
5185 
5186 /*
5187  * setStmfState
5188  *
5189  * stmfState - pointer to caller set state structure
5190  * objectType - one of:
5191  *		LOGICAL_UNIT_TYPE
5192  *		TARGET_TYPE
5193  *		STMF_SERVICE_TYPE
5194  */
5195 static int
5196 setStmfState(int fd, stmf_state_desc_t *stmfState, int objectType)
5197 {
5198 	int ret = STMF_STATUS_SUCCESS;
5199 	int ioctlRet;
5200 	int cmd;
5201 	stmf_iocdata_t stmfIoctl;
5202 
5203 	switch (objectType) {
5204 		case LOGICAL_UNIT_TYPE:
5205 			cmd = STMF_IOCTL_SET_LU_STATE;
5206 			break;
5207 		case TARGET_TYPE:
5208 			cmd = STMF_IOCTL_SET_TARGET_PORT_STATE;
5209 			break;
5210 		case STMF_SERVICE_TYPE:
5211 			cmd = STMF_IOCTL_SET_STMF_STATE;
5212 			break;
5213 		default:
5214 			ret = STMF_STATUS_ERROR;
5215 			goto done;
5216 	}
5217 
5218 	bzero(&stmfIoctl, sizeof (stmfIoctl));
5219 	/*
5220 	 * Issue ioctl to set the stmf state
5221 	 */
5222 	stmfIoctl.stmf_version = STMF_VERSION_1;
5223 	stmfIoctl.stmf_ibuf_size = sizeof (stmf_state_desc_t);
5224 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)stmfState;
5225 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
5226 	if (ioctlRet != 0) {
5227 		switch (errno) {
5228 			case EBUSY:
5229 				ret = STMF_ERROR_BUSY;
5230 				break;
5231 			case EPERM:
5232 			case EACCES:
5233 				ret = STMF_ERROR_PERM;
5234 				break;
5235 			case ENOENT:
5236 				ret = STMF_ERROR_NOT_FOUND;
5237 				break;
5238 			default:
5239 				syslog(LOG_DEBUG,
5240 				    "setStmfState:ioctl errno(%d)", errno);
5241 				ret = STMF_STATUS_ERROR;
5242 				break;
5243 		}
5244 	}
5245 done:
5246 	return (ret);
5247 }
5248 
5249 /*
5250  * stmfOnline
5251  *
5252  * Purpose: Online stmf service
5253  *
5254  */
5255 int
5256 stmfOnline(void)
5257 {
5258 	int ret;
5259 	int fd;
5260 	stmfState state;
5261 	stmf_state_desc_t iState;
5262 
5263 	ret = stmfGetState(&state);
5264 	if (ret == STMF_STATUS_SUCCESS) {
5265 		if (state.operationalState == STMF_SERVICE_STATE_ONLINE) {
5266 			return (STMF_ERROR_SERVICE_ONLINE);
5267 		}
5268 	} else {
5269 		return (STMF_STATUS_ERROR);
5270 	}
5271 	iState.state = STMF_STATE_ONLINE;
5272 	iState.config_state = STMF_CONFIG_NONE;
5273 	/*
5274 	 * Open control node for stmf
5275 	 * to make call to setStmfState()
5276 	 */
5277 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
5278 		return (ret);
5279 	ret = setStmfState(fd, &iState, STMF_SERVICE_TYPE);
5280 	(void) close(fd);
5281 	return (ret);
5282 }
5283 
5284 /*
5285  * stmfOffline
5286  *
5287  * Purpose: Offline stmf service
5288  *
5289  */
5290 int
5291 stmfOffline(void)
5292 {
5293 	int ret;
5294 	int fd;
5295 	stmfState state;
5296 	stmf_state_desc_t iState;
5297 
5298 	ret = stmfGetState(&state);
5299 	if (ret == STMF_STATUS_SUCCESS) {
5300 		if (state.operationalState == STMF_SERVICE_STATE_OFFLINE) {
5301 			return (STMF_ERROR_SERVICE_OFFLINE);
5302 		}
5303 	} else {
5304 		return (STMF_STATUS_ERROR);
5305 	}
5306 	iState.state = STMF_STATE_OFFLINE;
5307 	iState.config_state = STMF_CONFIG_NONE;
5308 
5309 	/*
5310 	 * Open control node for stmf
5311 	 * to make call to setStmfState()
5312 	 */
5313 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
5314 		return (ret);
5315 	ret = setStmfState(fd, &iState, STMF_SERVICE_TYPE);
5316 	(void) close(fd);
5317 	return (ret);
5318 }
5319 
5320 
5321 /*
5322  * stmfOfflineTarget
5323  *
5324  * Purpose: Change state of target to offline
5325  *
5326  * devid - devid of the target to offline
5327  */
5328 int
5329 stmfOfflineTarget(stmfDevid *devid)
5330 {
5331 	stmf_state_desc_t targetState;
5332 	int ret = STMF_STATUS_SUCCESS;
5333 	int fd;
5334 
5335 	if (devid == NULL) {
5336 		return (STMF_ERROR_INVALID_ARG);
5337 	}
5338 	bzero(&targetState, sizeof (targetState));
5339 
5340 	targetState.state = STMF_STATE_OFFLINE;
5341 	targetState.ident[IDENT_LENGTH_BYTE] = devid->identLength;
5342 	bcopy(&(devid->ident), &targetState.ident[IDENT_LENGTH_BYTE + 1],
5343 	    devid->identLength);
5344 	/*
5345 	 * Open control node for stmf
5346 	 * to make call to setStmfState()
5347 	 */
5348 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
5349 		return (ret);
5350 	ret = setStmfState(fd, &targetState, TARGET_TYPE);
5351 	(void) close(fd);
5352 	return (ret);
5353 }
5354 
5355 /*
5356  * stmfOfflineLogicalUnit
5357  *
5358  * Purpose: Change state of logical unit to offline
5359  *
5360  * lu - guid of the logical unit to offline
5361  */
5362 int
5363 stmfOfflineLogicalUnit(stmfGuid *lu)
5364 {
5365 	stmf_state_desc_t luState;
5366 	int ret = STMF_STATUS_SUCCESS;
5367 	int fd;
5368 
5369 	if (lu == NULL) {
5370 		return (STMF_ERROR_INVALID_ARG);
5371 	}
5372 
5373 	bzero(&luState, sizeof (luState));
5374 
5375 	luState.state = STMF_STATE_OFFLINE;
5376 	bcopy(lu, &luState.ident, sizeof (stmfGuid));
5377 	/*
5378 	 * Open control node for stmf
5379 	 * to make call to setStmfState()
5380 	 */
5381 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
5382 		return (ret);
5383 	ret = setStmfState(fd, &luState, LOGICAL_UNIT_TYPE);
5384 	(void) close(fd);
5385 	return (ret);
5386 }
5387 
5388 /*
5389  * stmfOnlineTarget
5390  *
5391  * Purpose: Change state of target to online
5392  *
5393  * devid - devid of the target to online
5394  */
5395 int
5396 stmfOnlineTarget(stmfDevid *devid)
5397 {
5398 	stmf_state_desc_t targetState;
5399 	int ret = STMF_STATUS_SUCCESS;
5400 	int fd;
5401 
5402 	if (devid == NULL) {
5403 		return (STMF_ERROR_INVALID_ARG);
5404 	}
5405 	bzero(&targetState, sizeof (targetState));
5406 
5407 	targetState.state = STMF_STATE_ONLINE;
5408 	targetState.ident[IDENT_LENGTH_BYTE] = devid->identLength;
5409 	bcopy(&(devid->ident), &targetState.ident[IDENT_LENGTH_BYTE + 1],
5410 	    devid->identLength);
5411 	/*
5412 	 * Open control node for stmf
5413 	 * to make call to setStmfState()
5414 	 */
5415 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
5416 		return (ret);
5417 	ret = setStmfState(fd, &targetState, TARGET_TYPE);
5418 	(void) close(fd);
5419 	return (ret);
5420 }
5421 
5422 /*
5423  * stmfOnlineLogicalUnit
5424  *
5425  * Purpose: Change state of logical unit to online
5426  *
5427  * lu - guid of the logical unit to online
5428  */
5429 int
5430 stmfOnlineLogicalUnit(stmfGuid *lu)
5431 {
5432 	stmf_state_desc_t luState;
5433 	int ret = STMF_STATUS_SUCCESS;
5434 	int fd;
5435 
5436 	if (lu == NULL) {
5437 		return (STMF_ERROR_INVALID_ARG);
5438 	}
5439 
5440 	bzero(&luState, sizeof (luState));
5441 
5442 	luState.state = STMF_STATE_ONLINE;
5443 	bcopy(lu, &luState.ident, sizeof (stmfGuid));
5444 	/*
5445 	 * Open control node for stmf
5446 	 * to make call to setStmfState()
5447 	 */
5448 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
5449 		return (ret);
5450 	ret = setStmfState(fd, &luState, LOGICAL_UNIT_TYPE);
5451 	(void) close(fd);
5452 	return (ret);
5453 }
5454 
5455 /*
5456  * stmfRemoveFromHostGroup
5457  *
5458  * Purpose: Removes an initiator from an initiator group
5459  *
5460  * hostGroupName - name of an initiator group
5461  * hostName - name of host group member to remove
5462  */
5463 int
5464 stmfRemoveFromHostGroup(stmfGroupName *hostGroupName, stmfDevid *hostName)
5465 {
5466 	int ret;
5467 	int fd;
5468 
5469 	if (hostGroupName == NULL ||
5470 	    (strnlen((char *)hostGroupName, sizeof (stmfGroupName))
5471 	    == sizeof (stmfGroupName)) || hostName == NULL) {
5472 		return (STMF_ERROR_INVALID_ARG);
5473 	}
5474 
5475 	/* call init */
5476 	ret = initializeConfig();
5477 	if (ret != STMF_STATUS_SUCCESS) {
5478 		return (ret);
5479 	}
5480 
5481 	/*
5482 	 * Open control node for stmf
5483 	 */
5484 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
5485 		return (ret);
5486 
5487 	if ((ret = groupMemberIoctl(fd, STMF_IOCTL_REMOVE_HG_ENTRY,
5488 	    hostGroupName, hostName)) != STMF_STATUS_SUCCESS) {
5489 		goto done;
5490 	}
5491 
5492 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
5493 		goto done;
5494 	}
5495 
5496 	ret = psRemoveHostGroupMember((char *)hostGroupName,
5497 	    (char *)hostName->ident);
5498 	switch (ret) {
5499 		case STMF_PS_SUCCESS:
5500 			ret = STMF_STATUS_SUCCESS;
5501 			break;
5502 		case STMF_PS_ERROR_MEMBER_NOT_FOUND:
5503 			ret = STMF_ERROR_MEMBER_NOT_FOUND;
5504 			break;
5505 		case STMF_PS_ERROR_GROUP_NOT_FOUND:
5506 			ret = STMF_ERROR_GROUP_NOT_FOUND;
5507 			break;
5508 		case STMF_PS_ERROR_BUSY:
5509 			ret = STMF_ERROR_BUSY;
5510 			break;
5511 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
5512 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
5513 			break;
5514 		case STMF_PS_ERROR_VERSION_MISMATCH:
5515 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
5516 			break;
5517 		default:
5518 			syslog(LOG_DEBUG,
5519 			    "stmfRemoveFromHostGroup"
5520 			    "psRemoveHostGroupMember:error(%d)", ret);
5521 			ret = STMF_STATUS_ERROR;
5522 			break;
5523 	}
5524 
5525 done:
5526 	(void) close(fd);
5527 	return (ret);
5528 }
5529 
5530 /*
5531  * stmfRemoveFromTargetGroup
5532  *
5533  * Purpose: Removes a local port from a local port group
5534  *
5535  * targetGroupName - name of a target group
5536  * targetName - name of target to remove
5537  */
5538 int
5539 stmfRemoveFromTargetGroup(stmfGroupName *targetGroupName, stmfDevid *targetName)
5540 {
5541 	int ret;
5542 	int fd;
5543 
5544 	if (targetGroupName == NULL ||
5545 	    (strnlen((char *)targetGroupName, sizeof (stmfGroupName))
5546 	    == sizeof (stmfGroupName)) || targetName == NULL) {
5547 		return (STMF_ERROR_INVALID_ARG);
5548 	}
5549 
5550 	/* call init */
5551 	ret = initializeConfig();
5552 	if (ret != STMF_STATUS_SUCCESS) {
5553 		return (ret);
5554 	}
5555 
5556 	/*
5557 	 * Open control node for stmf
5558 	 */
5559 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
5560 		return (ret);
5561 
5562 	if ((ret = groupMemberIoctl(fd, STMF_IOCTL_REMOVE_TG_ENTRY,
5563 	    targetGroupName, targetName)) != STMF_STATUS_SUCCESS) {
5564 		goto done;
5565 	}
5566 
5567 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
5568 		goto done;
5569 	}
5570 
5571 	ret = psRemoveTargetGroupMember((char *)targetGroupName,
5572 	    (char *)targetName->ident);
5573 	switch (ret) {
5574 		case STMF_PS_SUCCESS:
5575 			ret = STMF_STATUS_SUCCESS;
5576 			break;
5577 		case STMF_PS_ERROR_MEMBER_NOT_FOUND:
5578 			ret = STMF_ERROR_MEMBER_NOT_FOUND;
5579 			break;
5580 		case STMF_PS_ERROR_GROUP_NOT_FOUND:
5581 			ret = STMF_ERROR_GROUP_NOT_FOUND;
5582 			break;
5583 		case STMF_PS_ERROR_BUSY:
5584 			ret = STMF_ERROR_BUSY;
5585 			break;
5586 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
5587 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
5588 			break;
5589 		case STMF_PS_ERROR_VERSION_MISMATCH:
5590 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
5591 			break;
5592 		default:
5593 			syslog(LOG_DEBUG,
5594 			    "stmfRemoveFromTargetGroup"
5595 			    "psRemoveTargetGroupMember:error(%d)", ret);
5596 			ret = STMF_STATUS_ERROR;
5597 			break;
5598 	}
5599 
5600 done:
5601 	(void) close(fd);
5602 	return (ret);
5603 }
5604 
5605 /*
5606  * stmfRemoveViewEntry
5607  *
5608  * Purpose: Removes a view entry from a logical unit
5609  *
5610  * lu - guid of lu for which view entry is being removed
5611  * viewEntryIndex - index of view entry to remove
5612  *
5613  */
5614 int
5615 stmfRemoveViewEntry(stmfGuid *lu, uint32_t viewEntryIndex)
5616 {
5617 	int ret = STMF_STATUS_SUCCESS;
5618 	int fd;
5619 	int ioctlRet;
5620 	stmf_iocdata_t stmfIoctl;
5621 	stmf_view_op_entry_t ioctlViewEntry;
5622 
5623 	if (lu == NULL) {
5624 		return (STMF_ERROR_INVALID_ARG);
5625 	}
5626 
5627 	/* call init */
5628 	ret = initializeConfig();
5629 	if (ret != STMF_STATUS_SUCCESS) {
5630 		return (ret);
5631 	}
5632 
5633 	/*
5634 	 * Open control node for stmf
5635 	 */
5636 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
5637 		return (ret);
5638 
5639 	bzero(&ioctlViewEntry, sizeof (ioctlViewEntry));
5640 	ioctlViewEntry.ve_ndx_valid = B_TRUE;
5641 	ioctlViewEntry.ve_ndx = viewEntryIndex;
5642 	bcopy(lu, &ioctlViewEntry.ve_guid, sizeof (stmfGuid));
5643 
5644 	bzero(&stmfIoctl, sizeof (stmfIoctl));
5645 	/*
5646 	 * Issue ioctl to add to the view entry
5647 	 */
5648 	stmfIoctl.stmf_version = STMF_VERSION_1;
5649 	stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry);
5650 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry;
5651 	ioctlRet = ioctl(fd, STMF_IOCTL_REMOVE_VIEW_ENTRY, &stmfIoctl);
5652 	if (ioctlRet != 0) {
5653 		switch (errno) {
5654 			case EBUSY:
5655 				ret = STMF_ERROR_BUSY;
5656 				break;
5657 			case EPERM:
5658 				ret = STMF_ERROR_PERM;
5659 				break;
5660 			case EACCES:
5661 				switch (stmfIoctl.stmf_error) {
5662 					case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
5663 						ret = STMF_ERROR_CONFIG_NONE;
5664 						break;
5665 					default:
5666 						ret = STMF_ERROR_PERM;
5667 						break;
5668 				}
5669 				break;
5670 			case ENODEV:
5671 			case ENOENT:
5672 				ret = STMF_ERROR_NOT_FOUND;
5673 				break;
5674 			default:
5675 				syslog(LOG_DEBUG,
5676 				    "stmfRemoveViewEntry:ioctl errno(%d)",
5677 				    errno);
5678 				ret = STMF_STATUS_ERROR;
5679 				break;
5680 		}
5681 		goto done;
5682 	}
5683 
5684 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
5685 		goto done;
5686 	}
5687 
5688 	ret = psRemoveViewEntry(lu, viewEntryIndex);
5689 	switch (ret) {
5690 		case STMF_PS_SUCCESS:
5691 			ret = STMF_STATUS_SUCCESS;
5692 			break;
5693 		case STMF_PS_ERROR_NOT_FOUND:
5694 			ret = STMF_ERROR_NOT_FOUND;
5695 			break;
5696 		case STMF_PS_ERROR_BUSY:
5697 			ret = STMF_ERROR_BUSY;
5698 			break;
5699 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
5700 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
5701 			break;
5702 		case STMF_PS_ERROR_VERSION_MISMATCH:
5703 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
5704 			break;
5705 		default:
5706 			syslog(LOG_DEBUG,
5707 			    "stmfRemoveViewEntry" "psRemoveViewEntry:error(%d)",
5708 			    ret);
5709 			ret = STMF_STATUS_ERROR;
5710 			break;
5711 	}
5712 
5713 done:
5714 	(void) close(fd);
5715 	return (ret);
5716 }
5717 
5718 /*
5719  * stmfSetProviderData
5720  *
5721  * Purpose: set the provider data
5722  *
5723  * providerName - unique name of provider
5724  * nvl - nvlist to set
5725  * providerType - type of provider for which to set data
5726  *		STMF_LU_PROVIDER_TYPE
5727  *		STMF_PORT_PROVIDER_TYPE
5728  */
5729 int
5730 stmfSetProviderData(char *providerName, nvlist_t *nvl, int providerType)
5731 {
5732 	return (stmfSetProviderDataProt(providerName, nvl, providerType,
5733 	    NULL));
5734 }
5735 
5736 /*
5737  * stmfSetProviderDataProt
5738  *
5739  * Purpose: set the provider data
5740  *
5741  * providerName - unique name of provider
5742  * nvl - nvlist to set
5743  * providerType - type of provider for which to set data
5744  *		STMF_LU_PROVIDER_TYPE
5745  *		STMF_PORT_PROVIDER_TYPE
5746  * setToken - Stale data token returned in the stmfGetProviderDataProt()
5747  *	      call or NULL.
5748  */
5749 int
5750 stmfSetProviderDataProt(char *providerName, nvlist_t *nvl, int providerType,
5751     uint64_t *setToken)
5752 {
5753 	int ret;
5754 	int fd;
5755 
5756 	if (providerName == NULL || nvl == NULL) {
5757 		return (STMF_ERROR_INVALID_ARG);
5758 	}
5759 
5760 	if (providerType != STMF_LU_PROVIDER_TYPE &&
5761 	    providerType != STMF_PORT_PROVIDER_TYPE) {
5762 		return (STMF_ERROR_INVALID_ARG);
5763 	}
5764 
5765 	/* call init */
5766 	ret = initializeConfig();
5767 	if (ret != STMF_STATUS_SUCCESS) {
5768 		return (ret);
5769 	}
5770 
5771 	/*
5772 	 * Open control node for stmf
5773 	 */
5774 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
5775 		return (ret);
5776 
5777 	ret = setProviderData(fd, providerName, nvl, providerType, setToken);
5778 
5779 	(void) close(fd);
5780 
5781 	if (ret != STMF_STATUS_SUCCESS) {
5782 		goto done;
5783 	}
5784 
5785 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
5786 		goto done;
5787 	}
5788 
5789 	/* setting driver provider data successful. Now persist it */
5790 	ret = psSetProviderData(providerName, nvl, providerType, NULL);
5791 	switch (ret) {
5792 		case STMF_PS_SUCCESS:
5793 			ret = STMF_STATUS_SUCCESS;
5794 			break;
5795 		case STMF_PS_ERROR_EXISTS:
5796 			ret = STMF_ERROR_EXISTS;
5797 			break;
5798 		case STMF_PS_ERROR_BUSY:
5799 			ret = STMF_ERROR_BUSY;
5800 			break;
5801 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
5802 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
5803 			break;
5804 		case STMF_PS_ERROR_VERSION_MISMATCH:
5805 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
5806 			break;
5807 		case STMF_PS_ERROR_PROV_DATA_STALE:
5808 			ret = STMF_ERROR_PROV_DATA_STALE;
5809 			break;
5810 		default:
5811 			syslog(LOG_DEBUG,
5812 			    "stmfSetProviderData"
5813 			    "psSetProviderData:error(%d)", ret);
5814 			ret = STMF_STATUS_ERROR;
5815 			break;
5816 	}
5817 
5818 done:
5819 	return (ret);
5820 }
5821 
5822 /*
5823  * getProviderData
5824  *
5825  * Purpose: set the provider data from stmf
5826  *
5827  * providerName - unique name of provider
5828  * nvl - nvlist to load/retrieve
5829  * providerType - logical unit or port provider
5830  * setToken - returned stale data token
5831  */
5832 int
5833 getProviderData(char *providerName, nvlist_t **nvl, int providerType,
5834     uint64_t *setToken)
5835 {
5836 	int ret = STMF_STATUS_SUCCESS;
5837 	int fd;
5838 	int ioctlRet;
5839 	size_t nvlistSize = ALLOC_PP_DATA_SIZE;
5840 	int retryCnt = 0;
5841 	int retryCntMax = MAX_PROVIDER_RETRY;
5842 	stmf_ppioctl_data_t ppi = {0}, *ppi_out = NULL;
5843 	boolean_t retry = B_TRUE;
5844 	stmf_iocdata_t stmfIoctl;
5845 
5846 	if (providerName == NULL) {
5847 		return (STMF_ERROR_INVALID_ARG);
5848 	}
5849 
5850 	/*
5851 	 * Open control node for stmf
5852 	 */
5853 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
5854 		return (ret);
5855 
5856 	/* set provider name and provider type */
5857 	if (strlcpy(ppi.ppi_name, providerName,
5858 	    sizeof (ppi.ppi_name)) >=
5859 	    sizeof (ppi.ppi_name)) {
5860 		ret = STMF_ERROR_INVALID_ARG;
5861 		goto done;
5862 	}
5863 	switch (providerType) {
5864 		case STMF_LU_PROVIDER_TYPE:
5865 			ppi.ppi_lu_provider = 1;
5866 			break;
5867 		case STMF_PORT_PROVIDER_TYPE:
5868 			ppi.ppi_port_provider = 1;
5869 			break;
5870 		default:
5871 			ret = STMF_ERROR_INVALID_ARG;
5872 			goto done;
5873 	}
5874 
5875 	do {
5876 		/* allocate memory for ioctl */
5877 		ppi_out = (stmf_ppioctl_data_t *)calloc(1, nvlistSize +
5878 		    sizeof (stmf_ppioctl_data_t));
5879 		if (ppi_out == NULL) {
5880 			ret = STMF_ERROR_NOMEM;
5881 			goto done;
5882 
5883 		}
5884 
5885 		/* set the size of the ioctl data to allocated buffer */
5886 		ppi.ppi_data_size = nvlistSize;
5887 
5888 		bzero(&stmfIoctl, sizeof (stmfIoctl));
5889 
5890 		stmfIoctl.stmf_version = STMF_VERSION_1;
5891 		stmfIoctl.stmf_ibuf_size = sizeof (stmf_ppioctl_data_t);
5892 		stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ppi;
5893 		stmfIoctl.stmf_obuf_size = sizeof (stmf_ppioctl_data_t) +
5894 		    nvlistSize;
5895 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)ppi_out;
5896 		ioctlRet = ioctl(fd, STMF_IOCTL_GET_PP_DATA, &stmfIoctl);
5897 		if (ioctlRet != 0) {
5898 			switch (errno) {
5899 				case EBUSY:
5900 					ret = STMF_ERROR_BUSY;
5901 					break;
5902 				case EPERM:
5903 				case EACCES:
5904 					ret = STMF_ERROR_PERM;
5905 					break;
5906 				case EINVAL:
5907 					if (stmfIoctl.stmf_error ==
5908 					    STMF_IOCERR_INSUFFICIENT_BUF) {
5909 						nvlistSize =
5910 						    ppi_out->ppi_data_size;
5911 						free(ppi_out);
5912 						ppi_out = NULL;
5913 						if (retryCnt++ > retryCntMax) {
5914 							retry = B_FALSE;
5915 							ret = STMF_ERROR_BUSY;
5916 						} else {
5917 							ret =
5918 							    STMF_STATUS_SUCCESS;
5919 						}
5920 					} else {
5921 						syslog(LOG_DEBUG,
5922 						    "getProviderData:ioctl"
5923 						    "unable to retrieve "
5924 						    "nvlist");
5925 						ret = STMF_STATUS_ERROR;
5926 					}
5927 					break;
5928 				case ENOENT:
5929 					ret = STMF_ERROR_NOT_FOUND;
5930 					break;
5931 				default:
5932 					syslog(LOG_DEBUG,
5933 					    "getProviderData:ioctl errno(%d)",
5934 					    errno);
5935 					ret = STMF_STATUS_ERROR;
5936 					break;
5937 			}
5938 			if (ret != STMF_STATUS_SUCCESS)
5939 				goto done;
5940 		}
5941 	} while (retry && stmfIoctl.stmf_error == STMF_IOCERR_INSUFFICIENT_BUF);
5942 
5943 	if ((ret = nvlist_unpack((char *)ppi_out->ppi_data,
5944 	    ppi_out->ppi_data_size, nvl, 0)) != 0) {
5945 		ret = STMF_STATUS_ERROR;
5946 		goto done;
5947 	}
5948 
5949 	/* caller has asked for new token */
5950 	if (setToken) {
5951 		*setToken = ppi_out->ppi_token;
5952 	}
5953 done:
5954 	free(ppi_out);
5955 	(void) close(fd);
5956 	return (ret);
5957 }
5958 
5959 /*
5960  * setProviderData
5961  *
5962  * Purpose: set the provider data in stmf
5963  *
5964  * providerName - unique name of provider
5965  * nvl - nvlist to set
5966  * providerType - logical unit or port provider
5967  * setToken - stale data token to check if not NULL
5968  */
5969 static int
5970 setProviderData(int fd, char *providerName, nvlist_t *nvl, int providerType,
5971     uint64_t *setToken)
5972 {
5973 	int ret = STMF_STATUS_SUCCESS;
5974 	int ioctlRet;
5975 	size_t nvlistEncodedSize;
5976 	stmf_ppioctl_data_t *ppi = NULL;
5977 	uint64_t outToken;
5978 	char *allocatedNvBuffer;
5979 	stmf_iocdata_t stmfIoctl;
5980 
5981 	if (providerName == NULL) {
5982 		return (STMF_ERROR_INVALID_ARG);
5983 	}
5984 
5985 	/* get size of encoded nvlist */
5986 	if (nvlist_size(nvl, &nvlistEncodedSize, NV_ENCODE_XDR) != 0) {
5987 		return (STMF_STATUS_ERROR);
5988 	}
5989 
5990 	/* allocate memory for ioctl */
5991 	ppi = (stmf_ppioctl_data_t *)calloc(1, nvlistEncodedSize +
5992 	    sizeof (stmf_ppioctl_data_t));
5993 	if (ppi == NULL) {
5994 		return (STMF_ERROR_NOMEM);
5995 	}
5996 
5997 	if (setToken) {
5998 		ppi->ppi_token_valid = 1;
5999 		ppi->ppi_token = *setToken;
6000 	}
6001 
6002 	allocatedNvBuffer = (char *)&ppi->ppi_data;
6003 	if (nvlist_pack(nvl, &allocatedNvBuffer, &nvlistEncodedSize,
6004 	    NV_ENCODE_XDR, 0) != 0) {
6005 		return (STMF_STATUS_ERROR);
6006 	}
6007 
6008 	/* set provider name and provider type */
6009 	(void) strncpy(ppi->ppi_name, providerName, sizeof (ppi->ppi_name));
6010 	switch (providerType) {
6011 		case STMF_LU_PROVIDER_TYPE:
6012 			ppi->ppi_lu_provider = 1;
6013 			break;
6014 		case STMF_PORT_PROVIDER_TYPE:
6015 			ppi->ppi_port_provider = 1;
6016 			break;
6017 		default:
6018 			return (STMF_ERROR_INVALID_ARG);
6019 	}
6020 
6021 	/* set the size of the ioctl data to packed data size */
6022 	ppi->ppi_data_size = nvlistEncodedSize;
6023 
6024 	bzero(&stmfIoctl, sizeof (stmfIoctl));
6025 
6026 	stmfIoctl.stmf_version = STMF_VERSION_1;
6027 	/*
6028 	 * Subtracting 8 from the size as that is the size of the last member
6029 	 * of the structure where the packed data resides
6030 	 */
6031 	stmfIoctl.stmf_ibuf_size = nvlistEncodedSize +
6032 	    sizeof (stmf_ppioctl_data_t) - 8;
6033 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)ppi;
6034 	stmfIoctl.stmf_obuf_size = sizeof (uint64_t);
6035 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&outToken;
6036 	ioctlRet = ioctl(fd, STMF_IOCTL_LOAD_PP_DATA, &stmfIoctl);
6037 	if (ioctlRet != 0) {
6038 		switch (errno) {
6039 			case EBUSY:
6040 				ret = STMF_ERROR_BUSY;
6041 				break;
6042 			case EPERM:
6043 			case EACCES:
6044 				ret = STMF_ERROR_PERM;
6045 				break;
6046 			case EINVAL:
6047 				if (stmfIoctl.stmf_error ==
6048 				    STMF_IOCERR_PPD_UPDATED) {
6049 					ret = STMF_ERROR_PROV_DATA_STALE;
6050 				} else {
6051 					ret = STMF_STATUS_ERROR;
6052 				}
6053 				break;
6054 			default:
6055 				syslog(LOG_DEBUG,
6056 				    "setProviderData:ioctl errno(%d)", errno);
6057 				ret = STMF_STATUS_ERROR;
6058 				break;
6059 		}
6060 		if (ret != STMF_STATUS_SUCCESS)
6061 			goto done;
6062 	}
6063 
6064 	/* caller has asked for new token */
6065 	if (setToken) {
6066 		*setToken = outToken;
6067 	}
6068 done:
6069 	free(ppi);
6070 	return (ret);
6071 }
6072 
6073 /*
6074  * set the persistence method in the library only or library and service
6075  */
6076 int
6077 stmfSetPersistMethod(uint8_t persistType, boolean_t serviceSet)
6078 {
6079 	int ret = STMF_STATUS_SUCCESS;
6080 	int oldPersist;
6081 
6082 	(void) pthread_mutex_lock(&persistenceTypeLock);
6083 	oldPersist = iPersistType;
6084 	if (persistType == STMF_PERSIST_NONE ||
6085 	    persistType == STMF_PERSIST_SMF) {
6086 		iLibSetPersist = B_TRUE;
6087 		iPersistType = persistType;
6088 	} else {
6089 		(void) pthread_mutex_unlock(&persistenceTypeLock);
6090 		return (STMF_ERROR_INVALID_ARG);
6091 	}
6092 	/* Is this for this library open or in SMF */
6093 	if (serviceSet == B_TRUE) {
6094 		ret = psSetServicePersist(persistType);
6095 		if (ret != STMF_PS_SUCCESS) {
6096 			ret = STMF_ERROR_PERSIST_TYPE;
6097 			/* Set to old value */
6098 			iPersistType = oldPersist;
6099 		}
6100 	}
6101 	(void) pthread_mutex_unlock(&persistenceTypeLock);
6102 
6103 	return (ret);
6104 }
6105 
6106 /*
6107  * Only returns internal state for persist. If unset, goes to ps. If that
6108  * fails, returns default setting
6109  */
6110 static uint8_t
6111 iGetPersistMethod()
6112 {
6113 
6114 	uint8_t persistType = 0;
6115 
6116 	(void) pthread_mutex_lock(&persistenceTypeLock);
6117 	if (iLibSetPersist) {
6118 		persistType = iPersistType;
6119 	} else {
6120 		int ret;
6121 		ret = psGetServicePersist(&persistType);
6122 		if (ret != STMF_PS_SUCCESS) {
6123 			/* set to default */
6124 			persistType = STMF_DEFAULT_PERSIST;
6125 		}
6126 	}
6127 	(void) pthread_mutex_unlock(&persistenceTypeLock);
6128 	return (persistType);
6129 }
6130 
6131 /*
6132  * Returns either library state or persistent config state depending on
6133  * serviceState
6134  */
6135 int
6136 stmfGetPersistMethod(uint8_t *persistType, boolean_t serviceState)
6137 {
6138 	int ret = STMF_STATUS_SUCCESS;
6139 
6140 	if (persistType == NULL) {
6141 		return (STMF_ERROR_INVALID_ARG);
6142 	}
6143 	if (serviceState) {
6144 		ret = psGetServicePersist(persistType);
6145 		if (ret != STMF_PS_SUCCESS) {
6146 			ret = STMF_ERROR_PERSIST_TYPE;
6147 		}
6148 	} else {
6149 		(void) pthread_mutex_lock(&persistenceTypeLock);
6150 		if (iLibSetPersist) {
6151 			*persistType = iPersistType;
6152 		} else {
6153 			*persistType = STMF_DEFAULT_PERSIST;
6154 		}
6155 		(void) pthread_mutex_unlock(&persistenceTypeLock);
6156 	}
6157 
6158 	return (ret);
6159 }
6160 
6161 /*
6162  * stmfPostProxyMsg
6163  *
6164  * Purpose: Post a message to the proxy port provider
6165  *
6166  * buf - buffer containing message to post
6167  * buflen - buffer length
6168  */
6169 int
6170 stmfPostProxyMsg(int hdl, void *buf, uint32_t buflen)
6171 {
6172 	int ret = STMF_STATUS_SUCCESS;
6173 	int ioctlRet;
6174 	pppt_iocdata_t ppptIoctl = {0};
6175 
6176 	if (buf == NULL) {
6177 		return (STMF_ERROR_INVALID_ARG);
6178 	}
6179 
6180 	/*
6181 	 * Issue ioctl to post the message
6182 	 */
6183 	ppptIoctl.pppt_version = PPPT_VERSION_1;
6184 	ppptIoctl.pppt_buf_size = buflen;
6185 	ppptIoctl.pppt_buf = (uint64_t)(unsigned long)buf;
6186 	ioctlRet = ioctl(hdl, PPPT_MESSAGE, &ppptIoctl);
6187 	if (ioctlRet != 0) {
6188 		switch (errno) {
6189 			case EPERM:
6190 			case EACCES:
6191 				ret = STMF_ERROR_PERM;
6192 				break;
6193 			default:
6194 				ret = STMF_ERROR_POST_MSG_FAILED;
6195 				break;
6196 		}
6197 	}
6198 
6199 	return (ret);
6200 }
6201 
6202 /*
6203  * stmfInitProxyDoor
6204  *
6205  * Purpose: Install door in proxy
6206  *
6207  * hdl - pointer to returned handle
6208  * fd - door from door_create()
6209  */
6210 int
6211 stmfInitProxyDoor(int *hdl, int door)
6212 {
6213 	int ret = STMF_STATUS_SUCCESS;
6214 	int ioctlRet;
6215 	int fd;
6216 	pppt_iocdata_t ppptIoctl = {0};
6217 
6218 	if (hdl == NULL) {
6219 		return (STMF_ERROR_INVALID_ARG);
6220 	}
6221 
6222 	/*
6223 	 * Open control node for pppt
6224 	 */
6225 	if ((ret = openPppt(OPEN_PPPT, &fd)) != STMF_STATUS_SUCCESS) {
6226 		return (ret);
6227 	}
6228 
6229 	/*
6230 	 * Issue ioctl to install the door
6231 	 */
6232 	ppptIoctl.pppt_version = PPPT_VERSION_1;
6233 	ppptIoctl.pppt_door_fd = (uint32_t)door;
6234 	ioctlRet = ioctl(fd, PPPT_INSTALL_DOOR, &ppptIoctl);
6235 	if (ioctlRet != 0) {
6236 		switch (errno) {
6237 			case EPERM:
6238 			case EACCES:
6239 				ret = STMF_ERROR_PERM;
6240 				break;
6241 			case EINVAL:
6242 				ret = STMF_ERROR_INVALID_ARG;
6243 				break;
6244 			case EBUSY:
6245 				ret = STMF_ERROR_DOOR_INSTALLED;
6246 				break;
6247 			default:
6248 				ret = STMF_STATUS_ERROR;
6249 				break;
6250 		}
6251 	}
6252 
6253 	/* return driver fd to caller */
6254 	*hdl = fd;
6255 	return (ret);
6256 }
6257 
6258 void
6259 stmfDestroyProxyDoor(int hdl)
6260 {
6261 	(void) close(hdl);
6262 }
6263 
6264 /*
6265  * validateLunNumIoctl
6266  *
6267  * Purpose: Issues ioctl to check and get available lun# in view entry
6268  *
6269  * viewEntry - view entry to use
6270  */
6271 static int
6272 validateLunNumIoctl(int fd, stmfViewEntry *viewEntry)
6273 {
6274 	int ret = STMF_STATUS_SUCCESS;
6275 	int ioctlRet;
6276 	stmf_iocdata_t stmfIoctl;
6277 	stmf_view_op_entry_t ioctlViewEntry;
6278 
6279 	bzero(&ioctlViewEntry, sizeof (ioctlViewEntry));
6280 	/*
6281 	 * don't set ve_ndx or ve_ndx_valid as ve_ndx_valid should be
6282 	 * false on input
6283 	 */
6284 	ioctlViewEntry.ve_lu_number_valid = viewEntry->luNbrValid;
6285 	ioctlViewEntry.ve_all_hosts = viewEntry->allHosts;
6286 	ioctlViewEntry.ve_all_targets = viewEntry->allTargets;
6287 
6288 	if (viewEntry->allHosts == B_FALSE) {
6289 		bcopy(viewEntry->hostGroup, &ioctlViewEntry.ve_host_group.name,
6290 		    sizeof (stmfGroupName));
6291 		ioctlViewEntry.ve_host_group.name_size =
6292 		    strlen((char *)viewEntry->hostGroup);
6293 	}
6294 	if (viewEntry->allTargets == B_FALSE) {
6295 		bcopy(viewEntry->targetGroup,
6296 		    &ioctlViewEntry.ve_target_group.name,
6297 		    sizeof (stmfGroupName));
6298 		ioctlViewEntry.ve_target_group.name_size =
6299 		    strlen((char *)viewEntry->targetGroup);
6300 	}
6301 	/* Validating the lun number */
6302 	if (viewEntry->luNbrValid) {
6303 		bcopy(viewEntry->luNbr, &ioctlViewEntry.ve_lu_nbr,
6304 		    sizeof (ioctlViewEntry.ve_lu_nbr));
6305 	}
6306 
6307 	bzero(&stmfIoctl, sizeof (stmfIoctl));
6308 	/*
6309 	 * Issue ioctl to validate lun# in the view entry
6310 	 */
6311 	stmfIoctl.stmf_version = STMF_VERSION_1;
6312 	stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry);
6313 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry;
6314 	stmfIoctl.stmf_obuf_size = sizeof (ioctlViewEntry);
6315 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&ioctlViewEntry;
6316 	ioctlRet = ioctl(fd, STMF_IOCTL_VALIDATE_VIEW, &stmfIoctl);
6317 
6318 	/* save available lun number */
6319 	if (!viewEntry->luNbrValid) {
6320 		bcopy(ioctlViewEntry.ve_lu_nbr, viewEntry->luNbr,
6321 		    sizeof (ioctlViewEntry.ve_lu_nbr));
6322 	}
6323 	if (ioctlRet != 0) {
6324 		switch (errno) {
6325 			case EBUSY:
6326 				ret = STMF_ERROR_BUSY;
6327 				break;
6328 			case EPERM:
6329 				ret = STMF_ERROR_PERM;
6330 				break;
6331 			case EACCES:
6332 				switch (stmfIoctl.stmf_error) {
6333 					case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
6334 						ret = STMF_ERROR_CONFIG_NONE;
6335 						break;
6336 					default:
6337 						ret = STMF_ERROR_PERM;
6338 						break;
6339 				}
6340 				break;
6341 			default:
6342 				switch (stmfIoctl.stmf_error) {
6343 					case STMF_IOCERR_LU_NUMBER_IN_USE:
6344 						ret = STMF_ERROR_LUN_IN_USE;
6345 						break;
6346 					case STMF_IOCERR_VIEW_ENTRY_CONFLICT:
6347 						ret = STMF_ERROR_VE_CONFLICT;
6348 						break;
6349 					case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
6350 						ret = STMF_ERROR_CONFIG_NONE;
6351 						break;
6352 					case STMF_IOCERR_INVALID_HG:
6353 						ret = STMF_ERROR_INVALID_HG;
6354 						break;
6355 					case STMF_IOCERR_INVALID_TG:
6356 						ret = STMF_ERROR_INVALID_TG;
6357 						break;
6358 					default:
6359 						syslog(LOG_DEBUG,
6360 						    "addViewEntryIoctl"
6361 						    ":error(%d)",
6362 						    stmfIoctl.stmf_error);
6363 						ret = STMF_STATUS_ERROR;
6364 						break;
6365 				}
6366 				break;
6367 		}
6368 	}
6369 	return (ret);
6370 }
6371 
6372 /*
6373  * stmfValidateView
6374  *
6375  * Purpose: Validate or get lun # base on TG, HG of view entry
6376  *
6377  * viewEntry - view entry structure to use
6378  */
6379 int
6380 stmfValidateView(stmfViewEntry *viewEntry)
6381 {
6382 	int ret;
6383 	int fd;
6384 	stmfViewEntry iViewEntry;
6385 
6386 	if (viewEntry == NULL) {
6387 		return (STMF_ERROR_INVALID_ARG);
6388 	}
6389 
6390 	/* initialize and set internal view entry */
6391 	bzero(&iViewEntry, sizeof (iViewEntry));
6392 
6393 	if (!viewEntry->allHosts) {
6394 		bcopy(viewEntry->hostGroup, iViewEntry.hostGroup,
6395 		    sizeof (iViewEntry.hostGroup));
6396 	} else {
6397 		iViewEntry.allHosts = B_TRUE;
6398 	}
6399 
6400 	if (!viewEntry->allTargets) {
6401 		bcopy(viewEntry->targetGroup, iViewEntry.targetGroup,
6402 		    sizeof (iViewEntry.targetGroup));
6403 	} else {
6404 		iViewEntry.allTargets = B_TRUE;
6405 	}
6406 
6407 	if (viewEntry->luNbrValid) {
6408 		iViewEntry.luNbrValid = B_TRUE;
6409 		bcopy(viewEntry->luNbr, iViewEntry.luNbr,
6410 		    sizeof (iViewEntry.luNbr));
6411 	}
6412 
6413 	/*
6414 	 * set users return view entry index valid flag to false
6415 	 * in case of failure
6416 	 */
6417 	viewEntry->veIndexValid = B_FALSE;
6418 
6419 	/* Check to ensure service exists */
6420 	if (psCheckService() != STMF_STATUS_SUCCESS) {
6421 		return (STMF_ERROR_SERVICE_NOT_FOUND);
6422 	}
6423 
6424 	/* call init */
6425 	ret = initializeConfig();
6426 	if (ret != STMF_STATUS_SUCCESS) {
6427 		return (ret);
6428 	}
6429 
6430 	/*
6431 	 * Open control node for stmf
6432 	 */
6433 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
6434 		return (ret);
6435 
6436 	/*
6437 	 * Validate lun# in the view entry from the driver
6438 	 */
6439 	ret = validateLunNumIoctl(fd, &iViewEntry);
6440 	(void) close(fd);
6441 
6442 	/* save available lun number */
6443 	if (!viewEntry->luNbrValid) {
6444 		bcopy(iViewEntry.luNbr, viewEntry->luNbr,
6445 		    sizeof (iViewEntry.luNbr));
6446 	}
6447 
6448 	return (ret);
6449 }
6450