xref: /titanic_52/usr/src/lib/libstmf/common/stmf.c (revision 9e39c5ba00a55fa05777cc94b148296af305e135)
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 2008 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 <sys/stmf_ioctl.h>
47 
48 #define	STMF_PATH    "/devices/pseudo/stmf@0:admin"
49 
50 #define	EUI "eui."
51 #define	WWN "wwn."
52 #define	IQN "iqn."
53 #define	WWN_ASCII_SIZE 16
54 #define	IDENT_LENGTH_BYTE 3
55 
56 #define	MAX_LU		2<<16 - 1
57 #define	MAX_TARGET_PORT	1024
58 #define	MAX_PROVIDER	1024
59 #define	MAX_GROUP	1024
60 #define	MAX_SESSION	1024
61 #define	MAX_ISCSI_NAME	223
62 
63 #define	OPEN_STMF 0
64 #define	OPEN_EXCL_STMF O_EXCL
65 
66 #define	LOGICAL_UNIT_TYPE 0
67 #define	TARGET_TYPE 1
68 #define	STMF_SERVICE_TYPE 2
69 
70 static int openStmf(int, int *fd);
71 static int groupIoctl(int fd, int cmd, stmfGroupName *);
72 static int loadStore(int fd);
73 static int initializeConfig();
74 static int groupMemberIoctl(int fd, int cmd, stmfGroupName *, stmfDevid *);
75 static int guidCompare(const void *, const void *);
76 static int addViewEntryIoctl(int fd, stmfGuid *, stmfViewEntry *);
77 static int loadHostGroups(int fd, stmfGroupList *);
78 static int loadTargetGroups(int fd, stmfGroupList *);
79 static int getStmfState(stmf_state_desc_t *);
80 static int setStmfState(int fd, stmf_state_desc_t *, int);
81 static int setProviderData(int fd, char *, nvlist_t *, int);
82 
83 /*
84  * Open for stmf module
85  *
86  * flag - open flag (OPEN_STMF, OPEN_EXCL_STMF)
87  * fd - pointer to integer. On success, contains the stmf file descriptor
88  */
89 static int
90 openStmf(int flag, int *fd)
91 {
92 	int ret = STMF_STATUS_ERROR;
93 
94 	if ((*fd = open(STMF_PATH, O_NDELAY | O_RDONLY | flag)) != -1) {
95 		ret = STMF_STATUS_SUCCESS;
96 	} else {
97 		if (errno == EBUSY) {
98 			ret = STMF_ERROR_BUSY;
99 		} else {
100 			ret = STMF_STATUS_ERROR;
101 		}
102 		syslog(LOG_DEBUG, "openStmf:open failure:%s:errno(%d)",
103 		    STMF_PATH, errno);
104 	}
105 
106 	return (ret);
107 }
108 
109 /*
110  * initializeConfig
111  *
112  * This routine should be called before any ioctl requiring initialization
113  * which is basically everything except stmfGetState(), setStmfState() and
114  * stmfLoadConfig().
115  */
116 static int
117 initializeConfig()
118 {
119 	int ret;
120 	stmfState state;
121 
122 
123 	ret = stmfGetState(&state);
124 	if (ret != STMF_STATUS_SUCCESS) {
125 		return (ret);
126 	}
127 
128 	/* if we've already initialized or in the process, return success */
129 	if (state.configState == STMF_CONFIG_STATE_INIT_DONE ||
130 	    state.configState == STMF_CONFIG_STATE_INIT) {
131 		return (STMF_STATUS_SUCCESS);
132 	}
133 
134 	ret = stmfLoadConfig();
135 	if (ret != STMF_STATUS_SUCCESS) {
136 		syslog(LOG_DEBUG,
137 		    "initializeConfig:stmfLoadConfig:error(%d)", ret);
138 		return (ret);
139 	}
140 
141 	ret = stmfGetState(&state);
142 	if (ret != STMF_STATUS_SUCCESS) {
143 		syslog(LOG_DEBUG,
144 		    "initializeConfig:stmfGetState:error(%d)", ret);
145 		return (ret);
146 	}
147 
148 	if (state.configState != STMF_CONFIG_STATE_INIT_DONE) {
149 		syslog(LOG_DEBUG, "initializeConfig:state.configState(%d)",
150 		    state.configState);
151 		ret = STMF_STATUS_ERROR;
152 	}
153 
154 	return (ret);
155 }
156 
157 
158 /*
159  * groupIoctl
160  *
161  * Purpose: issue ioctl for create/delete on group
162  *
163  * cmd - valid STMF ioctl group cmd
164  * groupName - groupName to create or delete
165  */
166 static int
167 groupIoctl(int fd, int cmd, stmfGroupName *groupName)
168 {
169 	int ret = STMF_STATUS_SUCCESS;
170 	int ioctlRet;
171 	stmf_iocdata_t stmfIoctl;
172 	stmf_group_name_t iGroupName;
173 
174 	bzero(&iGroupName, sizeof (iGroupName));
175 
176 	bcopy(groupName, &iGroupName.name, strlen((char *)groupName));
177 
178 	iGroupName.name_size = strlen((char *)groupName);
179 
180 	bzero(&stmfIoctl, sizeof (stmfIoctl));
181 	/*
182 	 * Issue ioctl to create the host group
183 	 */
184 	stmfIoctl.stmf_version = STMF_VERSION_1;
185 	stmfIoctl.stmf_ibuf_size = sizeof (iGroupName);
186 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&iGroupName;
187 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
188 	if (ioctlRet != 0) {
189 		switch (errno) {
190 			case EACCES:
191 				ret = STMF_ERROR_PERM;
192 				break;
193 			default:
194 				switch (stmfIoctl.stmf_error) {
195 					case STMF_IOCERR_TG_EXISTS:
196 					case STMF_IOCERR_HG_EXISTS:
197 						ret = STMF_ERROR_EXISTS;
198 						break;
199 					case STMF_IOCERR_TG_IN_USE:
200 					case STMF_IOCERR_HG_IN_USE:
201 						ret = STMF_ERROR_GROUP_IN_USE;
202 						break;
203 					case STMF_IOCERR_INVALID_HG:
204 					case STMF_IOCERR_INVALID_TG:
205 						ret = STMF_ERROR_NOT_FOUND;
206 						break;
207 					default:
208 						syslog(LOG_DEBUG,
209 						    "groupIoctl:error(%d)",
210 						    stmfIoctl.stmf_error);
211 						ret = STMF_STATUS_ERROR;
212 						break;
213 				}
214 				break;
215 		}
216 	}
217 done:
218 	return (ret);
219 }
220 
221 /*
222  * groupIoctl
223  *
224  * Purpose: issue ioctl for add/remove member on group
225  *
226  * cmd - valid STMF ioctl group member cmd
227  * groupName - groupName to add to or remove from
228  * devid - group member to add or remove
229  */
230 static int
231 groupMemberIoctl(int fd, int cmd, stmfGroupName *groupName, stmfDevid *devid)
232 {
233 	int ret = STMF_STATUS_SUCCESS;
234 	int ioctlRet;
235 	stmf_iocdata_t stmfIoctl;
236 	stmf_group_op_data_t stmfGroupData;
237 
238 	bzero(&stmfGroupData, sizeof (stmfGroupData));
239 
240 	bcopy(groupName, &stmfGroupData.group.name, strlen((char *)groupName));
241 
242 	stmfGroupData.group.name_size = strlen((char *)groupName);
243 	stmfGroupData.ident[IDENT_LENGTH_BYTE] = devid->identLength;
244 	bcopy(&(devid->ident), &stmfGroupData.ident[IDENT_LENGTH_BYTE + 1],
245 	    devid->identLength);
246 
247 	bzero(&stmfIoctl, sizeof (stmfIoctl));
248 	/*
249 	 * Issue ioctl to add to the host group
250 	 */
251 	stmfIoctl.stmf_version = STMF_VERSION_1;
252 	stmfIoctl.stmf_ibuf_size = sizeof (stmfGroupData);
253 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&stmfGroupData;
254 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
255 	if (ioctlRet != 0) {
256 		switch (errno) {
257 			case EBUSY:
258 				ret = STMF_ERROR_BUSY;
259 				break;
260 			case EACCES:
261 				ret = STMF_ERROR_PERM;
262 				break;
263 			default:
264 				switch (stmfIoctl.stmf_error) {
265 					case STMF_IOCERR_TG_ENTRY_EXISTS:
266 					case STMF_IOCERR_HG_ENTRY_EXISTS:
267 						ret = STMF_ERROR_EXISTS;
268 						break;
269 					case STMF_IOCERR_INVALID_TG_ENTRY:
270 					case STMF_IOCERR_INVALID_HG_ENTRY:
271 						ret =
272 						    STMF_ERROR_MEMBER_NOT_FOUND;
273 						break;
274 					case STMF_IOCERR_INVALID_TG:
275 					case STMF_IOCERR_INVALID_HG:
276 						ret =
277 						    STMF_ERROR_GROUP_NOT_FOUND;
278 						break;
279 					default:
280 						syslog(LOG_DEBUG,
281 						    "groupMemberIoctl:error"
282 						    "(%d)",
283 						    stmfIoctl.stmf_error);
284 						ret = STMF_STATUS_ERROR;
285 						break;
286 				}
287 				break;
288 		}
289 	}
290 done:
291 	return (ret);
292 }
293 
294 /*
295  * guidCompare
296  *
297  * qsort function
298  * sort on guid
299  */
300 static int
301 guidCompare(const void *p1, const void *p2)
302 {
303 
304 	stmfGuid *g1 = (stmfGuid *)p1, *g2 = (stmfGuid *)p2;
305 	int i;
306 
307 	for (i = 0; i < sizeof (stmfGuid); i++) {
308 		if (g1->guid[i] > g2->guid[i])
309 			return (1);
310 		if (g1->guid[i] < g2->guid[i])
311 			return (-1);
312 	}
313 
314 	return (0);
315 }
316 
317 /*
318  * stmfAddToHostGroup
319  *
320  * Purpose: Adds an initiator to an existing host group
321  *
322  * hostGroupName - name of an existing host group
323  * hostName - name of initiator to add
324  */
325 int
326 stmfAddToHostGroup(stmfGroupName *hostGroupName, stmfDevid *hostName)
327 {
328 	int ret;
329 	int fd;
330 
331 	if (hostGroupName == NULL ||
332 	    (strnlen((char *)hostGroupName, sizeof (stmfGroupName))
333 	    == sizeof (stmfGroupName)) || hostName == NULL) {
334 		return (STMF_ERROR_INVALID_ARG);
335 	}
336 
337 	/* call init */
338 	ret = initializeConfig();
339 	if (ret != STMF_STATUS_SUCCESS) {
340 		return (ret);
341 	}
342 
343 	/*
344 	 * Open control node for stmf
345 	 */
346 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
347 		return (ret);
348 
349 	if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_HG_ENTRY, hostGroupName,
350 	    hostName)) != STMF_STATUS_SUCCESS) {
351 		goto done;
352 	}
353 
354 	ret = psAddHostGroupMember((char *)hostGroupName,
355 	    (char *)hostName->ident);
356 	switch (ret) {
357 		case STMF_PS_SUCCESS:
358 			ret = STMF_STATUS_SUCCESS;
359 			break;
360 		case STMF_PS_ERROR_EXISTS:
361 			ret = STMF_ERROR_EXISTS;
362 			break;
363 		case STMF_PS_ERROR_GROUP_NOT_FOUND:
364 			ret = STMF_ERROR_GROUP_NOT_FOUND;
365 			break;
366 		case STMF_PS_ERROR_BUSY:
367 			ret = STMF_ERROR_BUSY;
368 			break;
369 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
370 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
371 			break;
372 		case STMF_PS_ERROR_VERSION_MISMATCH:
373 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
374 			break;
375 		default:
376 			syslog(LOG_DEBUG,
377 			    "stmfAddToHostGroup:psAddHostGroupMember:error(%d)",
378 			    ret);
379 			ret = STMF_STATUS_ERROR;
380 			break;
381 	}
382 
383 done:
384 	(void) close(fd);
385 	return (ret);
386 }
387 
388 /*
389  * stmfAddToTargetGroup
390  *
391  * Purpose: Adds a local port to an existing target group
392  *
393  * targetGroupName - name of an existing target group
394  * targetName - name of target to add
395  */
396 int
397 stmfAddToTargetGroup(stmfGroupName *targetGroupName, stmfDevid *targetName)
398 {
399 	int ret;
400 	int fd;
401 	stmfState state;
402 
403 	if (targetGroupName == NULL ||
404 	    (strnlen((char *)targetGroupName, sizeof (stmfGroupName))
405 	    == sizeof (stmfGroupName)) || targetName == NULL) {
406 		return (STMF_ERROR_INVALID_ARG);
407 	}
408 
409 	ret = stmfGetState(&state);
410 	if (ret == STMF_STATUS_SUCCESS) {
411 		if (state.operationalState != STMF_SERVICE_STATE_OFFLINE) {
412 			return (STMF_ERROR_SERVICE_ONLINE);
413 		}
414 	} else {
415 		return (STMF_STATUS_ERROR);
416 	}
417 
418 	/* call init */
419 	ret = initializeConfig();
420 	if (ret != STMF_STATUS_SUCCESS) {
421 		return (ret);
422 	}
423 
424 	/*
425 	 * Open control node for stmf
426 	 */
427 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
428 		return (ret);
429 
430 	if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_TG_ENTRY,
431 	    targetGroupName, targetName)) != STMF_STATUS_SUCCESS) {
432 		goto done;
433 	}
434 
435 	ret = psAddTargetGroupMember((char *)targetGroupName,
436 	    (char *)targetName->ident);
437 	switch (ret) {
438 		case STMF_PS_SUCCESS:
439 			ret = STMF_STATUS_SUCCESS;
440 			break;
441 		case STMF_PS_ERROR_EXISTS:
442 			ret = STMF_ERROR_EXISTS;
443 			break;
444 		case STMF_PS_ERROR_GROUP_NOT_FOUND:
445 			ret = STMF_ERROR_GROUP_NOT_FOUND;
446 			break;
447 		case STMF_PS_ERROR_BUSY:
448 			ret = STMF_ERROR_BUSY;
449 			break;
450 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
451 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
452 			break;
453 		case STMF_PS_ERROR_VERSION_MISMATCH:
454 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
455 			break;
456 		default:
457 			syslog(LOG_DEBUG,
458 			    "stmfAddToTargetGroup:psAddTargetGroupMember:"
459 			    "error(%d)", ret);
460 			ret = STMF_STATUS_ERROR;
461 			break;
462 	}
463 
464 done:
465 	(void) close(fd);
466 	return (ret);
467 }
468 
469 /*
470  * addViewEntryIoctl
471  *
472  * Purpose: Issues ioctl to add a view entry
473  *
474  * lu - Logical Unit identifier to which the view entry is added
475  * viewEntry - view entry to add
476  * init - When set to B_TRUE, we are in the init state, i.e. don't call open
477  */
478 static int
479 addViewEntryIoctl(int fd, stmfGuid *lu, stmfViewEntry *viewEntry)
480 {
481 	int ret = STMF_STATUS_SUCCESS;
482 	int ioctlRet;
483 	stmf_iocdata_t stmfIoctl;
484 	stmf_view_op_entry_t ioctlViewEntry;
485 
486 	bzero(&ioctlViewEntry, sizeof (ioctlViewEntry));
487 	/*
488 	 * don't set ve_ndx or ve_ndx_valid as ve_ndx_valid should be
489 	 * false on input
490 	 */
491 	ioctlViewEntry.ve_lu_number_valid = viewEntry->luNbrValid;
492 	ioctlViewEntry.ve_all_hosts = viewEntry->allHosts;
493 	ioctlViewEntry.ve_all_targets = viewEntry->allTargets;
494 
495 	if (viewEntry->allHosts == B_FALSE) {
496 		bcopy(viewEntry->hostGroup, &ioctlViewEntry.ve_host_group.name,
497 		    sizeof (stmfGroupName));
498 		ioctlViewEntry.ve_host_group.name_size =
499 		    strlen((char *)viewEntry->hostGroup);
500 	}
501 	if (viewEntry->allTargets == B_FALSE) {
502 		bcopy(viewEntry->targetGroup,
503 		    &ioctlViewEntry.ve_target_group.name,
504 		    sizeof (stmfGroupName));
505 		ioctlViewEntry.ve_target_group.name_size =
506 		    strlen((char *)viewEntry->targetGroup);
507 	}
508 	if (viewEntry->luNbrValid) {
509 		bcopy(viewEntry->luNbr, &ioctlViewEntry.ve_lu_nbr,
510 		    sizeof (ioctlViewEntry.ve_lu_nbr));
511 	}
512 	bcopy(lu, &ioctlViewEntry.ve_guid, sizeof (stmfGuid));
513 
514 	bzero(&stmfIoctl, sizeof (stmfIoctl));
515 	/*
516 	 * Issue ioctl to add to the view entry
517 	 */
518 	stmfIoctl.stmf_version = STMF_VERSION_1;
519 	stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry);
520 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry;
521 	stmfIoctl.stmf_obuf_size = sizeof (ioctlViewEntry);
522 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&ioctlViewEntry;
523 	ioctlRet = ioctl(fd, STMF_IOCTL_ADD_VIEW_ENTRY, &stmfIoctl);
524 	if (ioctlRet != 0) {
525 		switch (errno) {
526 			case EBUSY:
527 				ret = STMF_ERROR_BUSY;
528 				break;
529 			case EACCES:
530 				switch (stmfIoctl.stmf_error) {
531 					case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
532 						ret = STMF_ERROR_CONFIG_NONE;
533 						break;
534 					default:
535 						ret = STMF_ERROR_PERM;
536 						break;
537 				}
538 				break;
539 			default:
540 				switch (stmfIoctl.stmf_error) {
541 					case STMF_IOCERR_LU_NUMBER_IN_USE:
542 						ret = STMF_ERROR_LUN_IN_USE;
543 						break;
544 					case STMF_IOCERR_VIEW_ENTRY_CONFLICT:
545 						ret = STMF_ERROR_VE_CONFLICT;
546 						break;
547 					case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
548 						ret = STMF_ERROR_CONFIG_NONE;
549 						break;
550 					case STMF_IOCERR_INVALID_HG:
551 						ret = STMF_ERROR_INVALID_HG;
552 						break;
553 					case STMF_IOCERR_INVALID_TG:
554 						ret = STMF_ERROR_INVALID_TG;
555 						break;
556 					default:
557 						syslog(LOG_DEBUG,
558 						    "addViewEntryIoctl"
559 						    ":error(%d)",
560 						    stmfIoctl.stmf_error);
561 						ret = STMF_STATUS_ERROR;
562 						break;
563 				}
564 				break;
565 		}
566 		goto done;
567 	}
568 
569 	/* copy lu nbr back to caller's view entry on success */
570 	viewEntry->veIndex = ioctlViewEntry.ve_ndx;
571 	if (ioctlViewEntry.ve_lu_number_valid) {
572 		bcopy(&ioctlViewEntry.ve_lu_nbr, viewEntry->luNbr,
573 		    sizeof (ioctlViewEntry.ve_lu_nbr));
574 	}
575 	viewEntry->luNbrValid = B_TRUE;
576 
577 done:
578 	return (ret);
579 }
580 
581 /*
582  * stmfAddViewEntry
583  *
584  * Purpose: Adds a view entry to a logical unit
585  *
586  * lu - guid of the logical unit to which the view entry is added
587  * viewEntry - view entry structure to add
588  */
589 int
590 stmfAddViewEntry(stmfGuid *lu, stmfViewEntry *viewEntry)
591 {
592 	int ret;
593 	int fd;
594 	stmfViewEntry iViewEntry;
595 
596 	if (lu == NULL || viewEntry == NULL) {
597 		return (STMF_ERROR_INVALID_ARG);
598 	}
599 
600 	/* initialize and set internal view entry */
601 	bzero(&iViewEntry, sizeof (iViewEntry));
602 
603 	if (!viewEntry->allHosts) {
604 		bcopy(viewEntry->hostGroup, iViewEntry.hostGroup,
605 		    sizeof (iViewEntry.hostGroup));
606 	} else {
607 		iViewEntry.allHosts = B_TRUE;
608 	}
609 
610 	if (!viewEntry->allTargets) {
611 		bcopy(viewEntry->targetGroup, iViewEntry.targetGroup,
612 		    sizeof (iViewEntry.targetGroup));
613 	} else {
614 		iViewEntry.allTargets = B_TRUE;
615 	}
616 
617 	if (viewEntry->luNbrValid) {
618 		iViewEntry.luNbrValid = B_TRUE;
619 		bcopy(viewEntry->luNbr, iViewEntry.luNbr,
620 		    sizeof (iViewEntry.luNbr));
621 	}
622 
623 	/*
624 	 * set users return view entry index valid flag to false
625 	 * in case of failure
626 	 */
627 	viewEntry->veIndexValid = B_FALSE;
628 
629 	/* Check to ensure service exists */
630 	if (psCheckService() != STMF_STATUS_SUCCESS) {
631 		return (STMF_ERROR_SERVICE_NOT_FOUND);
632 	}
633 
634 	/* call init */
635 	ret = initializeConfig();
636 	if (ret != STMF_STATUS_SUCCESS) {
637 		return (ret);
638 	}
639 
640 	/*
641 	 * Open control node for stmf
642 	 */
643 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
644 		return (ret);
645 
646 	/*
647 	 * First add the view entry to the driver
648 	 */
649 	ret = addViewEntryIoctl(fd, lu, &iViewEntry);
650 	if (ret != STMF_STATUS_SUCCESS) {
651 		goto done;
652 	}
653 
654 	/*
655 	 * If the add to driver was successful, add it to the persistent
656 	 * store.
657 	 */
658 	ret = psAddViewEntry(lu, &iViewEntry);
659 	switch (ret) {
660 		case STMF_PS_SUCCESS:
661 			ret = STMF_STATUS_SUCCESS;
662 			break;
663 		case STMF_PS_ERROR_NOT_FOUND:
664 			ret = STMF_ERROR_NOT_FOUND;
665 			break;
666 		case STMF_PS_ERROR_BUSY:
667 			ret = STMF_ERROR_BUSY;
668 			break;
669 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
670 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
671 			break;
672 		case STMF_PS_ERROR_VERSION_MISMATCH:
673 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
674 			break;
675 		default:
676 			syslog(LOG_DEBUG,
677 			    "stmfAddViewEntry:psAddViewEntry:error(%d)", ret);
678 			ret = STMF_STATUS_ERROR;
679 			break;
680 	}
681 
682 done:
683 	(void) close(fd);
684 
685 	if (ret == STMF_STATUS_SUCCESS) {
686 		/* set caller's view entry on success */
687 		viewEntry->veIndexValid = iViewEntry.veIndexValid;
688 		viewEntry->veIndex = iViewEntry.veIndex;
689 		viewEntry->luNbrValid = B_TRUE;
690 		bcopy(iViewEntry.luNbr, viewEntry->luNbr,
691 		    sizeof (iViewEntry.luNbr));
692 	}
693 	return (ret);
694 }
695 
696 /*
697  * stmfClearProviderData
698  *
699  * Purpose: delete all provider data for specified provider
700  *
701  * providerName - name of provider for which data should be deleted
702  */
703 int
704 stmfClearProviderData(char *providerName, int providerType)
705 {
706 	int ret;
707 	int fd;
708 	int ioctlRet;
709 	int savedErrno;
710 	stmf_iocdata_t stmfIoctl;
711 	stmf_ppioctl_data_t ppi;
712 
713 	/* call init */
714 	ret = initializeConfig();
715 	if (ret != STMF_STATUS_SUCCESS) {
716 		return (ret);
717 	}
718 
719 	if (providerName == NULL) {
720 		return (STMF_ERROR_INVALID_ARG);
721 	}
722 
723 	if (providerType != STMF_LU_PROVIDER_TYPE &&
724 	    providerType != STMF_PORT_PROVIDER_TYPE) {
725 		return (STMF_ERROR_INVALID_ARG);
726 	}
727 
728 	/*
729 	 * Open control node for stmf
730 	 */
731 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
732 		return (ret);
733 
734 	bzero(&ppi, sizeof (ppi));
735 
736 	(void) strncpy(ppi.ppi_name, providerName, sizeof (ppi.ppi_name));
737 
738 	switch (providerType) {
739 		case STMF_LU_PROVIDER_TYPE:
740 			ppi.ppi_lu_provider = 1;
741 			break;
742 		case STMF_PORT_PROVIDER_TYPE:
743 			ppi.ppi_port_provider = 1;
744 			break;
745 		default:
746 			ret = STMF_ERROR_INVALID_ARG;
747 			goto done;
748 	}
749 
750 	bzero(&stmfIoctl, sizeof (stmfIoctl));
751 
752 	stmfIoctl.stmf_version = STMF_VERSION_1;
753 	stmfIoctl.stmf_ibuf_size = sizeof (stmf_ppioctl_data_t);
754 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ppi;
755 
756 	ioctlRet = ioctl(fd, STMF_IOCTL_CLEAR_PP_DATA, &stmfIoctl);
757 	if (ioctlRet != 0) {
758 		savedErrno = errno;
759 		switch (savedErrno) {
760 			case EBUSY:
761 				ret = STMF_ERROR_BUSY;
762 				break;
763 			case EACCES:
764 				ret = STMF_ERROR_PERM;
765 				break;
766 			default:
767 				syslog(LOG_DEBUG,
768 				    "stmfClearProviderData:ioctl error(%d)",
769 				    ioctlRet);
770 				ret = STMF_STATUS_ERROR;
771 				break;
772 		}
773 		if (savedErrno != ENOENT) {
774 			goto done;
775 		}
776 	}
777 
778 	ret = psClearProviderData(providerName, providerType);
779 	switch (ret) {
780 		case STMF_PS_SUCCESS:
781 			ret = STMF_STATUS_SUCCESS;
782 			break;
783 		case STMF_PS_ERROR_NOT_FOUND:
784 			ret = STMF_ERROR_NOT_FOUND;
785 			break;
786 		case STMF_PS_ERROR_BUSY:
787 			ret = STMF_ERROR_BUSY;
788 			break;
789 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
790 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
791 			break;
792 		case STMF_PS_ERROR_VERSION_MISMATCH:
793 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
794 			break;
795 		default:
796 			syslog(LOG_DEBUG,
797 			    "stmfClearProviderData:psClearProviderData"
798 			    ":error(%d)", ret);
799 			ret = STMF_STATUS_ERROR;
800 			break;
801 	}
802 
803 done:
804 	(void) close(fd);
805 	return (ret);
806 }
807 
808 /*
809  * stmfCreateHostGroup
810  *
811  * Purpose: Create a new initiator group
812  *
813  * hostGroupName - name of host group to create
814  */
815 int
816 stmfCreateHostGroup(stmfGroupName *hostGroupName)
817 {
818 	int ret;
819 	int fd;
820 
821 	if (hostGroupName == NULL ||
822 	    (strnlen((char *)hostGroupName, sizeof (stmfGroupName))
823 	    == sizeof (stmfGroupName))) {
824 		return (STMF_ERROR_INVALID_ARG);
825 	}
826 
827 	/* Check to ensure service exists */
828 	if (psCheckService() != STMF_STATUS_SUCCESS) {
829 		return (STMF_ERROR_SERVICE_NOT_FOUND);
830 	}
831 
832 	/* call init */
833 	ret = initializeConfig();
834 	if (ret != STMF_STATUS_SUCCESS) {
835 		return (ret);
836 	}
837 
838 	/*
839 	 * Open control node for stmf
840 	 */
841 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
842 		return (ret);
843 
844 	if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_HOST_GROUP,
845 	    hostGroupName)) != STMF_STATUS_SUCCESS) {
846 		goto done;
847 	}
848 
849 	ret = psCreateHostGroup((char *)hostGroupName);
850 	switch (ret) {
851 		case STMF_PS_SUCCESS:
852 			ret = STMF_STATUS_SUCCESS;
853 			break;
854 		case STMF_PS_ERROR_EXISTS:
855 			ret = STMF_ERROR_EXISTS;
856 			break;
857 		case STMF_PS_ERROR_BUSY:
858 			ret = STMF_ERROR_BUSY;
859 			break;
860 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
861 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
862 			break;
863 		case STMF_PS_ERROR_VERSION_MISMATCH:
864 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
865 			break;
866 		default:
867 			syslog(LOG_DEBUG,
868 			    "stmfCreateHostGroup:psCreateHostGroup:error(%d)",
869 			    ret);
870 			ret = STMF_STATUS_ERROR;
871 			break;
872 	}
873 
874 done:
875 	(void) close(fd);
876 	return (ret);
877 }
878 
879 /*
880  * stmfCreateTargetGroup
881  *
882  * Purpose: Create a local port group
883  *
884  * targetGroupName - name of local port group to create
885  */
886 int
887 stmfCreateTargetGroup(stmfGroupName *targetGroupName)
888 {
889 	int ret;
890 	int fd;
891 
892 	if (targetGroupName == NULL ||
893 	    (strnlen((char *)targetGroupName, sizeof (stmfGroupName))
894 	    == sizeof (stmfGroupName))) {
895 		return (STMF_ERROR_INVALID_ARG);
896 	}
897 
898 	/* Check to ensure service exists */
899 	if (psCheckService() != STMF_STATUS_SUCCESS) {
900 		return (STMF_ERROR_SERVICE_NOT_FOUND);
901 	}
902 
903 	/* call init */
904 	ret = initializeConfig();
905 	if (ret != STMF_STATUS_SUCCESS) {
906 		return (ret);
907 	}
908 
909 	/*
910 	 * Open control node for stmf
911 	 */
912 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
913 		return (ret);
914 
915 	/*
916 	 * Add the group to the driver
917 	 */
918 	if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_TARGET_GROUP,
919 	    targetGroupName)) != STMF_STATUS_SUCCESS) {
920 		goto done;
921 	}
922 
923 	/*
924 	 * If the add to the driver was successful, add it to the persistent
925 	 * store.
926 	 */
927 	ret = psCreateTargetGroup((char *)targetGroupName);
928 	switch (ret) {
929 		case STMF_PS_SUCCESS:
930 			ret = STMF_STATUS_SUCCESS;
931 			break;
932 		case STMF_PS_ERROR_EXISTS:
933 			ret = STMF_ERROR_EXISTS;
934 			break;
935 		case STMF_PS_ERROR_BUSY:
936 			ret = STMF_ERROR_BUSY;
937 			break;
938 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
939 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
940 			break;
941 		case STMF_PS_ERROR_VERSION_MISMATCH:
942 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
943 			break;
944 		default:
945 			syslog(LOG_DEBUG,
946 			    "stmfCreateTargetGroup:psCreateTargetGroup"
947 			    ":error(%d)", ret);
948 			ret = STMF_STATUS_ERROR;
949 			break;
950 	}
951 
952 done:
953 	(void) close(fd);
954 	return (ret);
955 }
956 
957 /*
958  * stmfDeleteHostGroup
959  *
960  * Purpose: Delete an initiator or local port group
961  *
962  * hostGroupName - group to delete
963  */
964 int
965 stmfDeleteHostGroup(stmfGroupName *hostGroupName)
966 {
967 	int ret;
968 	int fd;
969 
970 	if (hostGroupName == NULL) {
971 		return (STMF_ERROR_INVALID_ARG);
972 	}
973 
974 	/* Check to ensure service exists */
975 	if (psCheckService() != STMF_STATUS_SUCCESS) {
976 		return (STMF_ERROR_SERVICE_NOT_FOUND);
977 	}
978 
979 	/* call init */
980 	ret = initializeConfig();
981 	if (ret != STMF_STATUS_SUCCESS) {
982 		return (ret);
983 	}
984 
985 	/*
986 	 * Open control node for stmf
987 	 */
988 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
989 		return (ret);
990 
991 	/*
992 	 * Remove the group from the driver
993 	 */
994 	if ((ret = groupIoctl(fd, STMF_IOCTL_REMOVE_HOST_GROUP,
995 	    hostGroupName)) != STMF_STATUS_SUCCESS) {
996 		goto done;
997 	}
998 
999 	/*
1000 	 * If the remove from the driver was successful, remove it from the
1001 	 * persistent store.
1002 	 */
1003 	ret = psDeleteHostGroup((char *)hostGroupName);
1004 	switch (ret) {
1005 		case STMF_PS_SUCCESS:
1006 			ret = STMF_STATUS_SUCCESS;
1007 			break;
1008 		case STMF_PS_ERROR_NOT_FOUND:
1009 			ret = STMF_ERROR_NOT_FOUND;
1010 			break;
1011 		case STMF_PS_ERROR_BUSY:
1012 			ret = STMF_ERROR_BUSY;
1013 			break;
1014 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
1015 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
1016 			break;
1017 		case STMF_PS_ERROR_VERSION_MISMATCH:
1018 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
1019 			break;
1020 		default:
1021 			syslog(LOG_DEBUG,
1022 			    "stmfDeleteHostGroup:psDeleteHostGroup:error(%d)",
1023 			    ret);
1024 			ret = STMF_STATUS_ERROR;
1025 			break;
1026 	}
1027 
1028 done:
1029 	(void) close(fd);
1030 	return (ret);
1031 }
1032 
1033 /*
1034  * stmfDeleteTargetGroup
1035  *
1036  * Purpose: Delete an initiator or local port group
1037  *
1038  * targetGroupName - group to delete
1039  */
1040 int
1041 stmfDeleteTargetGroup(stmfGroupName *targetGroupName)
1042 {
1043 	int ret = STMF_STATUS_SUCCESS;
1044 	int fd;
1045 
1046 	if (targetGroupName == NULL) {
1047 		return (STMF_ERROR_INVALID_ARG);
1048 	}
1049 
1050 	/* Check to ensure service exists */
1051 	if (psCheckService() != STMF_STATUS_SUCCESS) {
1052 		return (STMF_ERROR_SERVICE_NOT_FOUND);
1053 	}
1054 
1055 	/* call init */
1056 	ret = initializeConfig();
1057 	if (ret != STMF_STATUS_SUCCESS) {
1058 		return (ret);
1059 	}
1060 
1061 	/*
1062 	 * Open control node for stmf
1063 	 */
1064 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
1065 		return (ret);
1066 
1067 	/*
1068 	 * Remove the group from the driver
1069 	 */
1070 	if ((ret = groupIoctl(fd, STMF_IOCTL_REMOVE_TARGET_GROUP,
1071 	    targetGroupName)) != STMF_STATUS_SUCCESS) {
1072 		goto done;
1073 	}
1074 
1075 	/*
1076 	 * If the remove from the driver was successful, remove it from the
1077 	 * persistent store.
1078 	 */
1079 	ret = psDeleteTargetGroup((char *)targetGroupName);
1080 	switch (ret) {
1081 		case STMF_PS_SUCCESS:
1082 			ret = STMF_STATUS_SUCCESS;
1083 			break;
1084 		case STMF_PS_ERROR_NOT_FOUND:
1085 			ret = STMF_ERROR_NOT_FOUND;
1086 			break;
1087 		case STMF_PS_ERROR_BUSY:
1088 			ret = STMF_ERROR_BUSY;
1089 			break;
1090 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
1091 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
1092 			break;
1093 		case STMF_PS_ERROR_VERSION_MISMATCH:
1094 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
1095 			break;
1096 		default:
1097 			syslog(LOG_DEBUG,
1098 			    "stmfDeleteTargetGroup:psDeleteTargetGroup"
1099 			    ":error(%d)", ret);
1100 			ret = STMF_STATUS_ERROR;
1101 			break;
1102 	}
1103 
1104 done:
1105 	(void) close(fd);
1106 	return (ret);
1107 }
1108 
1109 /*
1110  * stmfDevidFromIscsiName
1111  *
1112  * Purpose: convert an iSCSI name to an stmf devid
1113  *
1114  * iscsiName - unicode nul terminated utf-8 encoded iSCSI name
1115  * devid - on success, contains the converted iscsi name
1116  */
1117 int
1118 stmfDevidFromIscsiName(char *iscsiName, stmfDevid *devid)
1119 {
1120 	if (devid == NULL || iscsiName == NULL)
1121 		return (STMF_ERROR_INVALID_ARG);
1122 
1123 	bzero(devid, sizeof (stmfDevid));
1124 
1125 	/* Validate size of target */
1126 	if ((devid->identLength = strlen(iscsiName)) > MAX_ISCSI_NAME ||
1127 	    devid->identLength < strlen(EUI) ||
1128 	    devid->identLength < strlen(IQN)) {
1129 		return (STMF_ERROR_INVALID_ARG);
1130 	}
1131 
1132 	if ((strncmp(iscsiName, EUI, strlen(EUI)) != 0) &&
1133 	    strncmp(iscsiName, IQN, strlen(IQN)) != 0) {
1134 		return (STMF_ERROR_INVALID_ARG);
1135 	}
1136 
1137 	/* copy UTF-8 bytes to ident */
1138 	bcopy(iscsiName, devid->ident, devid->identLength);
1139 
1140 	return (STMF_STATUS_SUCCESS);
1141 }
1142 
1143 /*
1144  * stmfDevidFromWwn
1145  *
1146  * Purpose: convert a WWN to an stmf devid
1147  *
1148  * wwn - 8-byte wwn identifier
1149  * devid - on success, contains the converted wwn
1150  */
1151 int
1152 stmfDevidFromWwn(uchar_t *wwn, stmfDevid *devid)
1153 {
1154 	if (wwn == NULL || devid == NULL)
1155 		return (STMF_ERROR_INVALID_ARG);
1156 
1157 	bzero(devid, sizeof (stmfDevid));
1158 
1159 	/* Copy eui prefix */
1160 	(void) bcopy(WWN, devid->ident, strlen(WWN));
1161 
1162 	/* Convert to ASCII uppercase hexadecimal string */
1163 	(void) snprintf((char *)&devid->ident[strlen(WWN)],
1164 	    sizeof (devid->ident), "%02X%02X%02X%02X%02X%02X%02X%02X",
1165 	    wwn[0], wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]);
1166 
1167 	devid->identLength = strlen((char *)devid->ident);
1168 
1169 	return (STMF_STATUS_SUCCESS);
1170 }
1171 
1172 /*
1173  * stmfFreeMemory
1174  *
1175  * Purpose: Free memory allocated by this library
1176  *
1177  * memory - previously allocated pointer of memory managed by library
1178  */
1179 void
1180 stmfFreeMemory(void *memory)
1181 {
1182 	free(memory);
1183 }
1184 
1185 /*
1186  * stmfGetHostGroupList
1187  *
1188  * Purpose: Retrieves the list of initiator group oids
1189  *
1190  * hostGroupList - pointer to pointer to hostGroupList structure
1191  *                 on success, this contains the host group list.
1192  */
1193 int
1194 stmfGetHostGroupList(stmfGroupList **hostGroupList)
1195 {
1196 	int ret;
1197 
1198 	if (hostGroupList == NULL) {
1199 		return (STMF_ERROR_INVALID_ARG);
1200 	}
1201 
1202 	ret = psGetHostGroupList(hostGroupList);
1203 	switch (ret) {
1204 		case STMF_PS_SUCCESS:
1205 			ret = STMF_STATUS_SUCCESS;
1206 			break;
1207 		case STMF_PS_ERROR_NOT_FOUND:
1208 			ret = STMF_ERROR_NOT_FOUND;
1209 			break;
1210 		case STMF_PS_ERROR_BUSY:
1211 			ret = STMF_ERROR_BUSY;
1212 			break;
1213 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
1214 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
1215 			break;
1216 		case STMF_PS_ERROR_VERSION_MISMATCH:
1217 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
1218 			break;
1219 		default:
1220 			syslog(LOG_DEBUG,
1221 			    "stmfGetHostGroupList:psGetHostGroupList:error(%d)",
1222 			    ret);
1223 			ret = STMF_STATUS_ERROR;
1224 			break;
1225 	}
1226 
1227 	return (ret);
1228 }
1229 
1230 /*
1231  * stmfGetHostGroupMembers
1232  *
1233  * Purpose: Retrieves the group properties for a host group
1234  *
1235  * groupName - name of group for which to retrieve host group members.
1236  * groupProp - pointer to pointer to stmfGroupProperties structure
1237  *             on success, this contains the list of group members.
1238  */
1239 int
1240 stmfGetHostGroupMembers(stmfGroupName *groupName,
1241     stmfGroupProperties **groupProp)
1242 {
1243 	int ret;
1244 
1245 	if (groupName == NULL || groupProp == NULL) {
1246 		return (STMF_ERROR_INVALID_ARG);
1247 	}
1248 
1249 	ret = psGetHostGroupMemberList((char *)groupName, groupProp);
1250 	switch (ret) {
1251 		case STMF_PS_SUCCESS:
1252 			ret = STMF_STATUS_SUCCESS;
1253 			break;
1254 		case STMF_PS_ERROR_NOT_FOUND:
1255 			ret = STMF_ERROR_NOT_FOUND;
1256 			break;
1257 		case STMF_PS_ERROR_BUSY:
1258 			ret = STMF_ERROR_BUSY;
1259 			break;
1260 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
1261 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
1262 			break;
1263 		case STMF_PS_ERROR_VERSION_MISMATCH:
1264 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
1265 			break;
1266 		default:
1267 			syslog(LOG_DEBUG,
1268 			    "stmfGetHostGroupMembers:psGetHostGroupMembers"
1269 			    ":error(%d)", ret);
1270 			ret = STMF_STATUS_ERROR;
1271 			break;
1272 	}
1273 
1274 	return (ret);
1275 }
1276 
1277 /*
1278  * stmfGetProviderData
1279  *
1280  * Purpose: Get provider data list
1281  *
1282  * providerName - name of provider for which to retrieve the data
1283  * nvl - pointer to nvlist_t pointer which will contain the nvlist data
1284  *       retrieved.
1285  * providerType - type of provider for which to retrieve data.
1286  *		    STMF_LU_PROVIDER_TYPE
1287  *		    STMF_PORT_PROVIDER_TYPE
1288  */
1289 int
1290 stmfGetProviderData(char *providerName, nvlist_t **nvl, int providerType)
1291 {
1292 	return (stmfGetProviderDataProt(providerName, nvl, providerType,
1293 	    NULL));
1294 }
1295 
1296 /*
1297  * stmfGetProviderDataProt
1298  *
1299  * Purpose: Get provider data list with token
1300  *
1301  * providerName - name of provider for which to retrieve the data
1302  * nvl - pointer to nvlist_t pointer which will contain the nvlist data
1303  *       retrieved.
1304  * providerType - type of provider for which to retrieve data.
1305  *		    STMF_LU_PROVIDER_TYPE
1306  *		    STMF_PORT_PROVIDER_TYPE
1307  * setToken - Returns the stale data token
1308  */
1309 int
1310 stmfGetProviderDataProt(char *providerName, nvlist_t **nvl, int providerType,
1311     uint64_t *setToken)
1312 {
1313 	int ret;
1314 
1315 	if (providerName == NULL || nvl == NULL) {
1316 		return (STMF_ERROR_INVALID_ARG);
1317 	}
1318 
1319 	if (providerType != STMF_LU_PROVIDER_TYPE &&
1320 	    providerType != STMF_PORT_PROVIDER_TYPE) {
1321 		return (STMF_ERROR_INVALID_ARG);
1322 	}
1323 
1324 	/* call init */
1325 	ret = initializeConfig();
1326 	if (ret != STMF_STATUS_SUCCESS) {
1327 		return (ret);
1328 	}
1329 
1330 	ret = psGetProviderData(providerName, nvl, providerType, setToken);
1331 	switch (ret) {
1332 		case STMF_PS_SUCCESS:
1333 			ret = STMF_STATUS_SUCCESS;
1334 			break;
1335 		case STMF_PS_ERROR_BUSY:
1336 			ret = STMF_ERROR_BUSY;
1337 			break;
1338 		case STMF_PS_ERROR_NOT_FOUND:
1339 			ret = STMF_ERROR_NOT_FOUND;
1340 			break;
1341 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
1342 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
1343 			break;
1344 		case STMF_PS_ERROR_VERSION_MISMATCH:
1345 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
1346 			break;
1347 		default:
1348 			syslog(LOG_DEBUG,
1349 			    "stmfGetProviderData:psGetProviderData:error(%d)",
1350 			    ret);
1351 			ret = STMF_STATUS_ERROR;
1352 			break;
1353 	}
1354 
1355 	return (ret);
1356 }
1357 
1358 /*
1359  * stmfGetProviderDataList
1360  *
1361  * Purpose: Get the list of providers currently persisting data
1362  *
1363  * providerList - pointer to pointer to an stmfProviderList structure allocated
1364  *                by the caller. Will contain the list of providers on success.
1365  */
1366 int
1367 stmfGetProviderDataList(stmfProviderList **providerList)
1368 {
1369 	int ret;
1370 
1371 	ret = psGetProviderDataList(providerList);
1372 	switch (ret) {
1373 		case STMF_PS_SUCCESS:
1374 			ret = STMF_STATUS_SUCCESS;
1375 			break;
1376 		case STMF_PS_ERROR_BUSY:
1377 			ret = STMF_ERROR_BUSY;
1378 			break;
1379 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
1380 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
1381 			break;
1382 		case STMF_PS_ERROR_VERSION_MISMATCH:
1383 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
1384 			break;
1385 		default:
1386 			syslog(LOG_DEBUG,
1387 			    "stmfGetProviderDataList:psGetProviderDataList"
1388 			    ":error(%d)", ret);
1389 			ret = STMF_STATUS_ERROR;
1390 			break;
1391 	}
1392 
1393 	return (ret);
1394 }
1395 
1396 
1397 /*
1398  * stmfGetSessionList
1399  *
1400  * Purpose: Retrieves the session list for a target (devid)
1401  *
1402  * devid - devid of target for which to retrieve session information.
1403  * sessionList - pointer to pointer to stmfSessionList structure
1404  *             on success, this contains the list of initiator sessions.
1405  */
1406 int
1407 stmfGetSessionList(stmfDevid *devid, stmfSessionList **sessionList)
1408 {
1409 	int ret = STMF_STATUS_SUCCESS;
1410 	int fd;
1411 	int ioctlRet;
1412 	int cmd = STMF_IOCTL_SESSION_LIST;
1413 	int i;
1414 	stmf_iocdata_t stmfIoctl;
1415 	slist_scsi_session_t *fSessionList;
1416 	uint8_t ident[260];
1417 	uint32_t fSessionListSize;
1418 
1419 	if (sessionList == NULL || devid == NULL) {
1420 		ret = STMF_ERROR_INVALID_ARG;
1421 	}
1422 
1423 	/* call init */
1424 	ret = initializeConfig();
1425 	if (ret != STMF_STATUS_SUCCESS) {
1426 		return (ret);
1427 	}
1428 
1429 	/*
1430 	 * Open control node for stmf
1431 	 */
1432 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
1433 		return (ret);
1434 
1435 	/*
1436 	 * Allocate ioctl input buffer
1437 	 */
1438 	fSessionListSize = MAX_SESSION;
1439 	fSessionListSize = fSessionListSize * (sizeof (slist_scsi_session_t));
1440 	fSessionList = (slist_scsi_session_t *)calloc(1, fSessionListSize);
1441 	if (fSessionList == NULL) {
1442 		return (STMF_ERROR_NOMEM);
1443 	}
1444 
1445 	ident[IDENT_LENGTH_BYTE] = devid->identLength;
1446 	bcopy(&(devid->ident), &ident[IDENT_LENGTH_BYTE + 1],
1447 	    devid->identLength);
1448 
1449 	bzero(&stmfIoctl, sizeof (stmfIoctl));
1450 	/*
1451 	 * Issue ioctl to get the session list
1452 	 */
1453 	stmfIoctl.stmf_version = STMF_VERSION_1;
1454 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ident;
1455 	stmfIoctl.stmf_ibuf_size = sizeof (ident);
1456 	stmfIoctl.stmf_obuf_size = fSessionListSize;
1457 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fSessionList;
1458 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
1459 	if (ioctlRet != 0) {
1460 		switch (errno) {
1461 			case EBUSY:
1462 				ret = STMF_ERROR_BUSY;
1463 				break;
1464 			case EACCES:
1465 				ret = STMF_ERROR_PERM;
1466 				break;
1467 			default:
1468 				syslog(LOG_DEBUG,
1469 				    "stmfGetSessionList:ioctl errno(%d)",
1470 				    errno);
1471 				ret = STMF_STATUS_ERROR;
1472 				break;
1473 		}
1474 		goto done;
1475 	}
1476 	/*
1477 	 * Check whether input buffer was large enough
1478 	 */
1479 	if (stmfIoctl.stmf_obuf_max_nentries > MAX_SESSION) {
1480 		fSessionListSize = stmfIoctl.stmf_obuf_max_nentries *
1481 		    sizeof (slist_scsi_session_t);
1482 		fSessionList = realloc(fSessionList, fSessionListSize);
1483 		if (fSessionList == NULL) {
1484 			return (STMF_ERROR_NOMEM);
1485 		}
1486 		stmfIoctl.stmf_obuf_size = fSessionListSize;
1487 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fSessionList;
1488 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
1489 		if (ioctlRet != 0) {
1490 			switch (errno) {
1491 				case EBUSY:
1492 					ret = STMF_ERROR_BUSY;
1493 					break;
1494 				case EACCES:
1495 					ret = STMF_ERROR_PERM;
1496 					break;
1497 				default:
1498 					syslog(LOG_DEBUG,
1499 					    "stmfGetSessionList:ioctl "
1500 					    "errno(%d)", errno);
1501 					ret = STMF_STATUS_ERROR;
1502 					break;
1503 			}
1504 			goto done;
1505 		}
1506 	}
1507 
1508 	/*
1509 	 * allocate caller's buffer with the final size
1510 	 */
1511 	*sessionList = (stmfSessionList *)calloc(1, sizeof (stmfSessionList) +
1512 	    stmfIoctl.stmf_obuf_max_nentries * sizeof (stmfSession));
1513 	if (*sessionList == NULL) {
1514 		ret = STMF_ERROR_NOMEM;
1515 		free(sessionList);
1516 		goto done;
1517 	}
1518 
1519 	(*sessionList)->cnt = stmfIoctl.stmf_obuf_max_nentries;
1520 
1521 	/*
1522 	 * copy session info to caller's buffer
1523 	 */
1524 	for (i = 0; i < (*sessionList)->cnt; i++) {
1525 		(*sessionList)->session[i].initiator.identLength =
1526 		    fSessionList->initiator[IDENT_LENGTH_BYTE];
1527 		bcopy(&(fSessionList->initiator[IDENT_LENGTH_BYTE + 1]),
1528 		    (*sessionList)->session[i].initiator.ident,
1529 		    STMF_IDENT_LENGTH);
1530 		bcopy(&(fSessionList->alias),
1531 		    &((*sessionList)->session[i].alias),
1532 		    sizeof ((*sessionList)->session[i].alias));
1533 		bcopy(&(fSessionList++->creation_time),
1534 		    &((*sessionList)->session[i].creationTime),
1535 		    sizeof (time_t));
1536 	}
1537 done:
1538 	(void) close(fd);
1539 	return (ret);
1540 }
1541 
1542 /*
1543  * stmfGetTargetGroupList
1544  *
1545  * Purpose: Retrieves the list of target groups
1546  *
1547  * targetGroupList - pointer to a pointer to an stmfGroupList structure. On
1548  *		     success, it contains the list of target groups.
1549  */
1550 int
1551 stmfGetTargetGroupList(stmfGroupList **targetGroupList)
1552 {
1553 	int ret;
1554 
1555 	if (targetGroupList == NULL) {
1556 		return (STMF_ERROR_INVALID_ARG);
1557 	}
1558 
1559 	ret = psGetTargetGroupList(targetGroupList);
1560 	switch (ret) {
1561 		case STMF_PS_SUCCESS:
1562 			ret = STMF_STATUS_SUCCESS;
1563 			break;
1564 		case STMF_PS_ERROR_NOT_FOUND:
1565 			ret = STMF_ERROR_NOT_FOUND;
1566 			break;
1567 		case STMF_PS_ERROR_BUSY:
1568 			ret = STMF_ERROR_BUSY;
1569 			break;
1570 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
1571 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
1572 			break;
1573 		case STMF_PS_ERROR_VERSION_MISMATCH:
1574 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
1575 			break;
1576 		default:
1577 			syslog(LOG_DEBUG,
1578 			    "stmfGetTargetGroupList:psGetTargetGroupList:"
1579 			    "error(%d)", ret);
1580 			ret = STMF_STATUS_ERROR;
1581 			break;
1582 	}
1583 
1584 	return (ret);
1585 }
1586 
1587 /*
1588  * stmfGetTargetGroupMembers
1589  *
1590  * Purpose: Retrieves the group members for a target group
1591  *
1592  * groupName - name of target group for which to retrieve members.
1593  * groupProp - pointer to pointer to stmfGroupProperties structure
1594  *             on success, this contains the list of group members.
1595  */
1596 int
1597 stmfGetTargetGroupMembers(stmfGroupName *groupName,
1598     stmfGroupProperties **groupProp)
1599 {
1600 	int ret;
1601 
1602 	if (groupName == NULL || groupProp == NULL) {
1603 		return (STMF_ERROR_INVALID_ARG);
1604 	}
1605 
1606 	ret = psGetTargetGroupMemberList((char *)groupName, groupProp);
1607 	switch (ret) {
1608 		case STMF_PS_SUCCESS:
1609 			ret = STMF_STATUS_SUCCESS;
1610 			break;
1611 		case STMF_PS_ERROR_NOT_FOUND:
1612 			ret = STMF_ERROR_NOT_FOUND;
1613 			break;
1614 		case STMF_PS_ERROR_BUSY:
1615 			ret = STMF_ERROR_BUSY;
1616 			break;
1617 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
1618 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
1619 			break;
1620 		case STMF_PS_ERROR_VERSION_MISMATCH:
1621 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
1622 			break;
1623 		default:
1624 			syslog(LOG_DEBUG,
1625 			    "stmfGetTargetGroupMembers:psGetTargetGroupMembers:"
1626 			    "error(%d)", ret);
1627 			ret = STMF_STATUS_ERROR;
1628 			break;
1629 	}
1630 
1631 	return (ret);
1632 }
1633 
1634 /*
1635  * stmfGetTargetList
1636  *
1637  * Purpose: Retrieves the list of target ports
1638  *
1639  * targetList - pointer to a pointer to an stmfDevidList structure.
1640  *		    On success, it contains the list of local ports (target).
1641  */
1642 int
1643 stmfGetTargetList(stmfDevidList **targetList)
1644 {
1645 	int ret;
1646 	int fd;
1647 	int ioctlRet;
1648 	int i;
1649 	stmf_iocdata_t stmfIoctl;
1650 	/* framework target port list */
1651 	slist_target_port_t *fTargetList, *fTargetListP;
1652 	uint32_t fTargetListSize;
1653 
1654 	if (targetList == NULL) {
1655 		return (STMF_ERROR_INVALID_ARG);
1656 	}
1657 
1658 	/* call init */
1659 	ret = initializeConfig();
1660 	if (ret != STMF_STATUS_SUCCESS) {
1661 		return (ret);
1662 	}
1663 
1664 	/*
1665 	 * Open control node for stmf
1666 	 */
1667 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
1668 		return (ret);
1669 
1670 	/*
1671 	 * Allocate ioctl input buffer
1672 	 */
1673 	fTargetListSize = MAX_TARGET_PORT * sizeof (slist_target_port_t);
1674 	fTargetListP = fTargetList =
1675 	    (slist_target_port_t *)calloc(1, fTargetListSize);
1676 	if (fTargetList == NULL) {
1677 		goto done;
1678 	}
1679 
1680 	bzero(&stmfIoctl, sizeof (stmfIoctl));
1681 	/*
1682 	 * Issue ioctl to retrieve target list
1683 	 */
1684 	stmfIoctl.stmf_version = STMF_VERSION_1;
1685 	stmfIoctl.stmf_obuf_size = fTargetListSize;
1686 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fTargetList;
1687 	ioctlRet = ioctl(fd, STMF_IOCTL_TARGET_PORT_LIST, &stmfIoctl);
1688 	if (ioctlRet != 0) {
1689 		switch (errno) {
1690 			case EBUSY:
1691 				ret = STMF_ERROR_BUSY;
1692 				break;
1693 			case EACCES:
1694 				ret = STMF_ERROR_PERM;
1695 				break;
1696 			default:
1697 				syslog(LOG_DEBUG,
1698 				    "stmfGetTargetList:ioctl errno(%d)", errno);
1699 				ret = STMF_STATUS_ERROR;
1700 				break;
1701 		}
1702 		goto done;
1703 	}
1704 	/*
1705 	 * Check whether input buffer was large enough
1706 	 */
1707 	if (stmfIoctl.stmf_obuf_max_nentries > MAX_TARGET_PORT) {
1708 		fTargetListSize = stmfIoctl.stmf_obuf_max_nentries *
1709 		    sizeof (slist_target_port_t);
1710 		fTargetListP = fTargetList =
1711 		    realloc(fTargetList, fTargetListSize);
1712 		if (fTargetList == NULL) {
1713 			return (STMF_ERROR_NOMEM);
1714 		}
1715 		stmfIoctl.stmf_obuf_size = fTargetListSize;
1716 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fTargetList;
1717 		ioctlRet = ioctl(fd, STMF_IOCTL_TARGET_PORT_LIST,
1718 		    &stmfIoctl);
1719 		if (ioctlRet != 0) {
1720 			switch (errno) {
1721 				case EBUSY:
1722 					ret = STMF_ERROR_BUSY;
1723 					break;
1724 				case EACCES:
1725 					ret = STMF_ERROR_PERM;
1726 					break;
1727 				default:
1728 					syslog(LOG_DEBUG,
1729 					    "stmfGetTargetList:ioctl errno(%d)",
1730 					    errno);
1731 					ret = STMF_STATUS_ERROR;
1732 					break;
1733 			}
1734 			goto done;
1735 		}
1736 	}
1737 
1738 	*targetList = (stmfDevidList *)calloc(1,
1739 	    stmfIoctl.stmf_obuf_max_nentries * sizeof (stmfDevid) +
1740 	    sizeof (stmfDevidList));
1741 
1742 	(*targetList)->cnt = stmfIoctl.stmf_obuf_max_nentries;
1743 	for (i = 0; i < stmfIoctl.stmf_obuf_max_nentries; i++, fTargetList++) {
1744 		(*targetList)->devid[i].identLength =
1745 		    fTargetList->target[IDENT_LENGTH_BYTE];
1746 		bcopy(&fTargetList->target[IDENT_LENGTH_BYTE + 1],
1747 		    &(*targetList)->devid[i].ident,
1748 		    fTargetList->target[IDENT_LENGTH_BYTE]);
1749 	}
1750 
1751 done:
1752 	(void) close(fd);
1753 	free(fTargetListP);
1754 	return (ret);
1755 }
1756 
1757 /*
1758  * stmfGetTargetProperties
1759  *
1760  * Purpose:  Retrieves the properties for a logical unit
1761  *
1762  * devid - devid of the target for which to retrieve properties
1763  * targetProps - pointer to an stmfTargetProperties structure.
1764  *		On success, it contains the target properties for
1765  *		the specified devid.
1766  */
1767 int
1768 stmfGetTargetProperties(stmfDevid *devid, stmfTargetProperties *targetProps)
1769 {
1770 	int ret = STMF_STATUS_SUCCESS;
1771 	int fd;
1772 	int ioctlRet;
1773 	stmf_iocdata_t stmfIoctl;
1774 	sioc_target_port_props_t targetProperties;
1775 
1776 	if (devid == NULL || targetProps == NULL) {
1777 		return (STMF_ERROR_INVALID_ARG);
1778 	}
1779 
1780 	/* call init */
1781 	ret = initializeConfig();
1782 	if (ret != STMF_STATUS_SUCCESS) {
1783 		return (ret);
1784 	}
1785 
1786 	/*
1787 	 * Open control node for stmf
1788 	 */
1789 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
1790 		return (ret);
1791 
1792 	targetProperties.tgt_id[IDENT_LENGTH_BYTE] = devid->identLength;
1793 	bcopy(&(devid->ident), &targetProperties.tgt_id[IDENT_LENGTH_BYTE + 1],
1794 	    devid->identLength);
1795 
1796 	bzero(&stmfIoctl, sizeof (stmfIoctl));
1797 	/*
1798 	 * Issue ioctl to add to the host group
1799 	 */
1800 	stmfIoctl.stmf_version = STMF_VERSION_1;
1801 	stmfIoctl.stmf_ibuf_size = sizeof (targetProperties.tgt_id);
1802 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&targetProperties.tgt_id;
1803 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&targetProperties;
1804 	stmfIoctl.stmf_obuf_size = sizeof (targetProperties);
1805 	ioctlRet = ioctl(fd, STMF_IOCTL_GET_TARGET_PORT_PROPERTIES,
1806 	    &stmfIoctl);
1807 	if (ioctlRet != 0) {
1808 		switch (errno) {
1809 			case EBUSY:
1810 				ret = STMF_ERROR_BUSY;
1811 				break;
1812 			case EACCES:
1813 				ret = STMF_ERROR_PERM;
1814 				break;
1815 			case ENOENT:
1816 				ret = STMF_ERROR_NOT_FOUND;
1817 				break;
1818 			default:
1819 				syslog(LOG_DEBUG,
1820 				    "stmfGetTargetProperties:ioctl errno(%d)",
1821 				    errno);
1822 				ret = STMF_STATUS_ERROR;
1823 				break;
1824 		}
1825 		goto done;
1826 	}
1827 
1828 	bcopy(targetProperties.tgt_provider_name, targetProps->providerName,
1829 	    sizeof (targetProperties.tgt_provider_name));
1830 	if (targetProperties.tgt_state == STMF_STATE_ONLINE) {
1831 		targetProps->status = STMF_TARGET_PORT_ONLINE;
1832 	} else if (targetProperties.tgt_state == STMF_STATE_OFFLINE) {
1833 		targetProps->status = STMF_TARGET_PORT_OFFLINE;
1834 	} else if (targetProperties.tgt_state == STMF_STATE_ONLINING) {
1835 		targetProps->status = STMF_TARGET_PORT_ONLINING;
1836 	} else if (targetProperties.tgt_state == STMF_STATE_OFFLINING) {
1837 		targetProps->status = STMF_TARGET_PORT_OFFLINING;
1838 	}
1839 	bcopy(targetProperties.tgt_alias, targetProps->alias,
1840 	    sizeof (targetProps->alias));
1841 done:
1842 	(void) close(fd);
1843 	return (ret);
1844 }
1845 
1846 /*
1847  * stmfGetLogicalUnitList
1848  *
1849  * Purpose: Retrieves list of logical unit Object IDs
1850  *
1851  * luList - pointer to a pointer to a stmfGuidList structure. On success,
1852  *          it contains the list of logical unit guids.
1853  *
1854  */
1855 int
1856 stmfGetLogicalUnitList(stmfGuidList **luList)
1857 {
1858 	int ret;
1859 	int fd;
1860 	int ioctlRet;
1861 	int cmd = STMF_IOCTL_LU_LIST;
1862 	int i, k;
1863 	stmf_iocdata_t stmfIoctl;
1864 	/* framework lu list */
1865 	slist_lu_t *fLuList;
1866 	/* persistent store lu list */
1867 	stmfGuidList *sLuList = NULL;
1868 	int finalListSize = 0;
1869 	int newAllocSize;
1870 	uint32_t fLuListSize;
1871 	uint32_t endList;
1872 
1873 	if (luList == NULL) {
1874 		return (STMF_ERROR_INVALID_ARG);
1875 	}
1876 
1877 	/* call init */
1878 	ret = initializeConfig();
1879 	if (ret != STMF_STATUS_SUCCESS) {
1880 		return (ret);
1881 	}
1882 
1883 	/*
1884 	 * Open control node for stmf
1885 	 */
1886 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
1887 		return (ret);
1888 
1889 	/*
1890 	 * Allocate ioctl input buffer
1891 	 */
1892 	fLuListSize = MAX_LU;
1893 	fLuListSize = fLuListSize * (sizeof (slist_lu_t));
1894 	fLuList = (slist_lu_t *)calloc(1, fLuListSize);
1895 	if (fLuList == NULL) {
1896 		return (STMF_ERROR_NOMEM);
1897 	}
1898 
1899 	bzero(&stmfIoctl, sizeof (stmfIoctl));
1900 	/*
1901 	 * Issue ioctl to get the LU list
1902 	 */
1903 	stmfIoctl.stmf_version = STMF_VERSION_1;
1904 	stmfIoctl.stmf_obuf_size = fLuListSize;
1905 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fLuList;
1906 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
1907 	if (ioctlRet != 0) {
1908 		switch (errno) {
1909 			case EBUSY:
1910 				ret = STMF_ERROR_BUSY;
1911 				break;
1912 			case EACCES:
1913 				ret = STMF_ERROR_PERM;
1914 				break;
1915 			default:
1916 				syslog(LOG_DEBUG,
1917 				    "stmfGetLogicalUnitList:ioctl errno(%d)",
1918 				    errno);
1919 				ret = STMF_STATUS_ERROR;
1920 				break;
1921 		}
1922 		goto done;
1923 	}
1924 	/*
1925 	 * Check whether input buffer was large enough
1926 	 */
1927 	if (stmfIoctl.stmf_obuf_max_nentries > MAX_LU) {
1928 		fLuListSize = stmfIoctl.stmf_obuf_max_nentries *
1929 		    sizeof (slist_lu_t);
1930 		fLuList = realloc(fLuList, fLuListSize);
1931 		if (fLuList == NULL) {
1932 			return (STMF_ERROR_NOMEM);
1933 		}
1934 		stmfIoctl.stmf_obuf_size = fLuListSize;
1935 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fLuList;
1936 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
1937 		if (ioctlRet != 0) {
1938 			switch (errno) {
1939 				case EBUSY:
1940 					ret = STMF_ERROR_BUSY;
1941 					break;
1942 				case EACCES:
1943 					ret = STMF_ERROR_PERM;
1944 					break;
1945 				default:
1946 					syslog(LOG_DEBUG,
1947 					    "stmfGetLogicalUnitList:"
1948 					    "ioctl errno(%d)", errno);
1949 					ret = STMF_STATUS_ERROR;
1950 					break;
1951 			}
1952 			goto done;
1953 		}
1954 	}
1955 
1956 	ret = psGetLogicalUnitList(&sLuList);
1957 	switch (ret) {
1958 		case STMF_PS_SUCCESS:
1959 			ret = STMF_STATUS_SUCCESS;
1960 			break;
1961 		case STMF_PS_ERROR_BUSY:
1962 			ret = STMF_ERROR_BUSY;
1963 			break;
1964 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
1965 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
1966 			break;
1967 		case STMF_PS_ERROR_VERSION_MISMATCH:
1968 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
1969 			break;
1970 		default:
1971 			syslog(LOG_DEBUG,
1972 			    "stmfGetLogicalUnitList:psGetLogicalUnitList"
1973 			    ":error(%d)", ret);
1974 			ret = STMF_STATUS_ERROR;
1975 			break;
1976 	}
1977 	if (ret != STMF_STATUS_SUCCESS) {
1978 		goto done;
1979 	}
1980 
1981 	/*
1982 	 * 2 lists must be merged
1983 	 * reallocate the store list to add the list from the
1984 	 * framework
1985 	 */
1986 	newAllocSize = sLuList->cnt * sizeof (stmfGuid) + sizeof (stmfGuidList)
1987 	    + stmfIoctl.stmf_obuf_nentries * sizeof (stmfGuid);
1988 
1989 	sLuList = realloc(sLuList, newAllocSize);
1990 	if (sLuList == NULL) {
1991 		ret = STMF_ERROR_NOMEM;
1992 		goto done;
1993 	}
1994 
1995 	/*
1996 	 * add list from ioctl. Start from end of list retrieved from store.
1997 	 */
1998 	endList = sLuList->cnt + stmfIoctl.stmf_obuf_nentries;
1999 	for (k = 0, i = sLuList->cnt; i < endList; i++, k++) {
2000 		bcopy(&fLuList[k].lu_guid, sLuList->guid[i].guid,
2001 		    sizeof (stmfGuid));
2002 	}
2003 	sLuList->cnt = endList;
2004 
2005 	/*
2006 	 * sort the list for merging
2007 	 */
2008 	qsort((void *)&(sLuList->guid[0]), sLuList->cnt,
2009 	    sizeof (stmfGuid), guidCompare);
2010 
2011 	/*
2012 	 * get final list count
2013 	 */
2014 	for (i = 0; i < sLuList->cnt; i++) {
2015 		if ((i + 1) <= sLuList->cnt) {
2016 			if (bcmp(sLuList->guid[i].guid, sLuList->guid[i+1].guid,
2017 			    sizeof (stmfGuid)) == 0) {
2018 				continue;
2019 			}
2020 		}
2021 		finalListSize++;
2022 	}
2023 
2024 	/*
2025 	 * allocate caller's buffer with the final size
2026 	 */
2027 	*luList = (stmfGuidList *)calloc(1, sizeof (stmfGuidList) +
2028 	    finalListSize * sizeof (stmfGuid));
2029 	if (*luList == NULL) {
2030 		ret = STMF_ERROR_NOMEM;
2031 		goto done;
2032 	}
2033 
2034 	/*
2035 	 * copy guids to caller's buffer
2036 	 */
2037 	for (k = 0, i = 0; i < sLuList->cnt; i++) {
2038 		if ((i + 1) <= sLuList->cnt) {
2039 			if (bcmp(sLuList->guid[i].guid, sLuList->guid[i+1].guid,
2040 			    sizeof (stmfGuid)) == 0) {
2041 				continue;
2042 			}
2043 		}
2044 		bcopy(&(sLuList->guid[i].guid), (*luList)->guid[k++].guid,
2045 		    sizeof (stmfGuid));
2046 	}
2047 
2048 	(*luList)->cnt = finalListSize;
2049 
2050 done:
2051 	(void) close(fd);
2052 	/*
2053 	 * free internal buffers
2054 	 */
2055 	free(fLuList);
2056 	free(sLuList);
2057 	return (ret);
2058 }
2059 
2060 /*
2061  * stmfGetLogicalUnitProperties
2062  *
2063  * Purpose:  Retrieves the properties for a logical unit
2064  *
2065  * lu - guid of the logical unit for which to retrieve properties
2066  * stmfLuProps - pointer to an stmfLogicalUnitProperties structure. On success,
2067  *               it contains the logical unit properties for the specified guid.
2068  */
2069 int
2070 stmfGetLogicalUnitProperties(stmfGuid *lu, stmfLogicalUnitProperties *luProps)
2071 {
2072 	int ret = STMF_STATUS_SUCCESS;
2073 	int stmfRet;
2074 	int fd;
2075 	int ioctlRet;
2076 	int cmd = STMF_IOCTL_GET_LU_PROPERTIES;
2077 	stmfViewEntryList *viewEntryList = NULL;
2078 	stmf_iocdata_t stmfIoctl;
2079 	sioc_lu_props_t fLuProps;
2080 
2081 	if (luProps == NULL || luProps == NULL) {
2082 		ret = STMF_ERROR_INVALID_ARG;
2083 	}
2084 
2085 	bzero(luProps, sizeof (stmfLogicalUnitProperties));
2086 
2087 	/* call init */
2088 	ret = initializeConfig();
2089 	if (ret != STMF_STATUS_SUCCESS) {
2090 		return (ret);
2091 	}
2092 
2093 	/*
2094 	 * Open control node for stmf
2095 	 */
2096 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
2097 		return (ret);
2098 
2099 	bzero(&stmfIoctl, sizeof (stmfIoctl));
2100 	/*
2101 	 * Issue ioctl to add to the host group
2102 	 */
2103 	stmfIoctl.stmf_version = STMF_VERSION_1;
2104 	stmfIoctl.stmf_ibuf_size = sizeof (stmfGuid);
2105 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)lu;
2106 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&fLuProps;
2107 	stmfIoctl.stmf_obuf_size = sizeof (fLuProps);
2108 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
2109 	if (ioctlRet != 0) {
2110 		switch (errno) {
2111 			case EBUSY:
2112 				ret = STMF_ERROR_BUSY;
2113 				break;
2114 			case EACCES:
2115 				ret = STMF_ERROR_PERM;
2116 				break;
2117 			case ENOENT:
2118 				stmfRet = stmfGetViewEntryList(lu,
2119 				    &viewEntryList);
2120 				if (stmfRet == STMF_STATUS_SUCCESS) {
2121 					luProps->status =
2122 					    STMF_LOGICAL_UNIT_UNREGISTERED;
2123 					if (viewEntryList->cnt > 0) {
2124 						ret = STMF_STATUS_SUCCESS;
2125 					} else {
2126 						ret = STMF_ERROR_NOT_FOUND;
2127 					}
2128 				} else {
2129 					ret = STMF_ERROR_NOT_FOUND;
2130 				}
2131 				stmfFreeMemory(viewEntryList);
2132 				break;
2133 			default:
2134 				syslog(LOG_DEBUG,
2135 				    "stmfGetLogicalUnit:ioctl errno(%d)",
2136 				    errno);
2137 				ret = STMF_STATUS_ERROR;
2138 				break;
2139 		}
2140 		goto done;
2141 	}
2142 
2143 	bcopy(fLuProps.lu_provider_name, luProps->providerName,
2144 	    sizeof (fLuProps.lu_provider_name));
2145 	if (fLuProps.lu_state == STMF_STATE_ONLINE) {
2146 		luProps->status = STMF_LOGICAL_UNIT_ONLINE;
2147 	} else if (fLuProps.lu_state == STMF_STATE_OFFLINE) {
2148 		luProps->status = STMF_LOGICAL_UNIT_OFFLINE;
2149 	} else if (fLuProps.lu_state == STMF_STATE_ONLINING) {
2150 		luProps->status = STMF_LOGICAL_UNIT_ONLINING;
2151 	} else if (fLuProps.lu_state == STMF_STATE_OFFLINING) {
2152 		luProps->status = STMF_LOGICAL_UNIT_OFFLINING;
2153 	}
2154 	bcopy(fLuProps.lu_alias, luProps->alias, sizeof (luProps->alias));
2155 done:
2156 	(void) close(fd);
2157 	return (ret);
2158 }
2159 
2160 /*
2161  * stmfGetState
2162  *
2163  * Purpose: retrieve the current state of the stmf module
2164  *
2165  * state - pointer to stmfState structure allocated by the caller
2166  *         On success, contains the state of stmf
2167  */
2168 int
2169 stmfGetState(stmfState *state)
2170 {
2171 	int ret;
2172 	stmf_state_desc_t iState;
2173 
2174 	if (state == NULL) {
2175 		return (STMF_ERROR_INVALID_ARG);
2176 	}
2177 
2178 	ret = getStmfState(&iState);
2179 	if (ret != STMF_STATUS_SUCCESS) {
2180 		return (ret);
2181 	}
2182 	switch (iState.state) {
2183 		case STMF_STATE_ONLINE:
2184 			state->operationalState =
2185 			    STMF_SERVICE_STATE_ONLINE;
2186 			break;
2187 		case STMF_STATE_OFFLINE:
2188 			state->operationalState =
2189 			    STMF_SERVICE_STATE_OFFLINE;
2190 			break;
2191 		case STMF_STATE_ONLINING:
2192 			state->operationalState =
2193 			    STMF_SERVICE_STATE_ONLINING;
2194 			break;
2195 		case STMF_STATE_OFFLINING:
2196 			state->operationalState =
2197 			    STMF_SERVICE_STATE_OFFLINING;
2198 			break;
2199 		default:
2200 			state->operationalState =
2201 			    STMF_SERVICE_STATE_UNKNOWN;
2202 			break;
2203 	}
2204 	switch (iState.config_state) {
2205 		case STMF_CONFIG_NONE:
2206 			state->configState = STMF_CONFIG_STATE_NONE;
2207 			break;
2208 		case STMF_CONFIG_INIT:
2209 			state->configState = STMF_CONFIG_STATE_INIT;
2210 			break;
2211 		case STMF_CONFIG_INIT_DONE:
2212 			state->configState =
2213 			    STMF_CONFIG_STATE_INIT_DONE;
2214 			break;
2215 		default:
2216 			state->configState =
2217 			    STMF_CONFIG_STATE_UNKNOWN;
2218 			break;
2219 	}
2220 	return (STMF_STATUS_SUCCESS);
2221 }
2222 
2223 /*
2224  * stmfGetViewEntryList
2225  *
2226  * Purpose: Retrieves the list of view entries for the specified
2227  *          logical unit.
2228  *
2229  * lu - the guid of the logical unit for which to retrieve the view entry list
2230  * viewEntryList - a pointer to a pointer to a stmfViewEntryList structure. On
2231  *                 success, contains the list of view entries.
2232  */
2233 int
2234 stmfGetViewEntryList(stmfGuid *lu, stmfViewEntryList **viewEntryList)
2235 {
2236 	int ret;
2237 
2238 	if (lu == NULL || viewEntryList == NULL) {
2239 		return (STMF_ERROR_INVALID_ARG);
2240 	}
2241 
2242 	ret = psGetViewEntryList(lu, viewEntryList);
2243 	switch (ret) {
2244 		case STMF_PS_SUCCESS:
2245 			ret = STMF_STATUS_SUCCESS;
2246 			break;
2247 		case STMF_PS_ERROR_NOT_FOUND:
2248 			ret = STMF_ERROR_NOT_FOUND;
2249 			break;
2250 		case STMF_PS_ERROR_BUSY:
2251 			ret = STMF_ERROR_BUSY;
2252 			break;
2253 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
2254 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
2255 			break;
2256 		case STMF_PS_ERROR_VERSION_MISMATCH:
2257 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
2258 			break;
2259 		default:
2260 			syslog(LOG_DEBUG,
2261 			    "stmfGetViewEntryList:error(%d)", ret);
2262 			ret = STMF_STATUS_ERROR;
2263 			break;
2264 	}
2265 
2266 	return (ret);
2267 }
2268 
2269 /*
2270  * loadHostGroups
2271  *
2272  * Purpose - issues the ioctl to load the host groups into stmf
2273  *
2274  * fd - file descriptor for the control node of stmf.
2275  * groupList - populated host group list
2276  */
2277 static int
2278 loadHostGroups(int fd, stmfGroupList *groupList)
2279 {
2280 	int i, j;
2281 	int ret = STMF_STATUS_SUCCESS;
2282 	stmfGroupProperties *groupProps = NULL;
2283 
2284 	for (i = 0; i < groupList->cnt; i++) {
2285 		if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_HOST_GROUP,
2286 		    &(groupList->name[i]))) != STMF_STATUS_SUCCESS) {
2287 			goto out;
2288 		}
2289 		ret = stmfGetHostGroupMembers(&(groupList->name[i]),
2290 		    &groupProps);
2291 		for (j = 0; j < groupProps->cnt; j++) {
2292 			if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_HG_ENTRY,
2293 			    &(groupList->name[i]), &(groupProps->name[j])))
2294 			    != STMF_STATUS_SUCCESS) {
2295 				goto out;
2296 			}
2297 		}
2298 	}
2299 
2300 
2301 out:
2302 	stmfFreeMemory(groupProps);
2303 	return (ret);
2304 }
2305 
2306 /*
2307  * loadTargetGroups
2308  *
2309  * Purpose - issues the ioctl to load the target groups into stmf
2310  *
2311  * fd - file descriptor for the control node of stmf.
2312  * groupList - populated target group list.
2313  */
2314 static int
2315 loadTargetGroups(int fd, stmfGroupList *groupList)
2316 {
2317 	int i, j;
2318 	int ret = STMF_STATUS_SUCCESS;
2319 	stmfGroupProperties *groupProps = NULL;
2320 
2321 	for (i = 0; i < groupList->cnt; i++) {
2322 		if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_TARGET_GROUP,
2323 		    &(groupList->name[i]))) != STMF_STATUS_SUCCESS) {
2324 			goto out;
2325 		}
2326 		ret = stmfGetTargetGroupMembers(&(groupList->name[i]),
2327 		    &groupProps);
2328 		for (j = 0; j < groupProps->cnt; j++) {
2329 			if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_TG_ENTRY,
2330 			    &(groupList->name[i]), &(groupProps->name[j])))
2331 			    != STMF_STATUS_SUCCESS) {
2332 				goto out;
2333 			}
2334 		}
2335 	}
2336 
2337 
2338 out:
2339 	stmfFreeMemory(groupProps);
2340 	return (ret);
2341 }
2342 
2343 
2344 /*
2345  * loadStore
2346  *
2347  * Purpose: Load the configuration data from the store
2348  *
2349  * First load the host groups and target groups, then the view entries
2350  * and finally the provider data
2351  *
2352  * fd - file descriptor of control node for stmf.
2353  */
2354 static int
2355 loadStore(int fd)
2356 {
2357 	int ret;
2358 	int i, j;
2359 	stmfGroupList *groupList = NULL;
2360 	stmfGuidList *guidList = NULL;
2361 	stmfViewEntryList *viewEntryList = NULL;
2362 	stmfProviderList *providerList = NULL;
2363 	int providerType;
2364 	nvlist_t *nvl = NULL;
2365 
2366 
2367 
2368 	/* load host groups */
2369 	ret = stmfGetHostGroupList(&groupList);
2370 	if (ret != STMF_STATUS_SUCCESS) {
2371 		return (ret);
2372 	}
2373 	ret = loadHostGroups(fd, groupList);
2374 	if (ret != STMF_STATUS_SUCCESS) {
2375 		goto out;
2376 	}
2377 
2378 	stmfFreeMemory(groupList);
2379 	groupList = NULL;
2380 
2381 	/* load target groups */
2382 	ret = stmfGetTargetGroupList(&groupList);
2383 	if (ret != STMF_STATUS_SUCCESS) {
2384 		goto out;
2385 	}
2386 	ret = loadTargetGroups(fd, groupList);
2387 	if (ret != STMF_STATUS_SUCCESS) {
2388 		goto out;
2389 	}
2390 
2391 	stmfFreeMemory(groupList);
2392 	groupList = NULL;
2393 
2394 	/* Get the guid list */
2395 	ret = psGetLogicalUnitList(&guidList);
2396 	switch (ret) {
2397 		case STMF_PS_SUCCESS:
2398 			ret = STMF_STATUS_SUCCESS;
2399 			break;
2400 		case STMF_PS_ERROR_NOT_FOUND:
2401 			ret = STMF_ERROR_NOT_FOUND;
2402 			break;
2403 		case STMF_PS_ERROR_BUSY:
2404 			ret = STMF_ERROR_BUSY;
2405 			break;
2406 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
2407 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
2408 			break;
2409 		case STMF_PS_ERROR_VERSION_MISMATCH:
2410 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
2411 			break;
2412 		default:
2413 			ret = STMF_STATUS_ERROR;
2414 			break;
2415 	}
2416 
2417 	if (ret != STMF_STATUS_SUCCESS) {
2418 		goto out;
2419 	}
2420 
2421 	/*
2422 	 * We have the guid list, now get the corresponding
2423 	 * view entries for each guid
2424 	 */
2425 	for (i = 0; i < guidList->cnt; i++) {
2426 		ret = psGetViewEntryList(&guidList->guid[i], &viewEntryList);
2427 		switch (ret) {
2428 			case STMF_PS_SUCCESS:
2429 				ret = STMF_STATUS_SUCCESS;
2430 				break;
2431 			case STMF_PS_ERROR_NOT_FOUND:
2432 				ret = STMF_ERROR_NOT_FOUND;
2433 				break;
2434 			case STMF_PS_ERROR_BUSY:
2435 				ret = STMF_ERROR_BUSY;
2436 				break;
2437 			case STMF_PS_ERROR_SERVICE_NOT_FOUND:
2438 				ret = STMF_ERROR_SERVICE_NOT_FOUND;
2439 				break;
2440 			case STMF_PS_ERROR_VERSION_MISMATCH:
2441 				ret = STMF_ERROR_SERVICE_DATA_VERSION;
2442 				break;
2443 			default:
2444 				ret = STMF_STATUS_ERROR;
2445 				break;
2446 		}
2447 		if (ret != STMF_STATUS_SUCCESS) {
2448 			goto out;
2449 		}
2450 		for (j = 0; j < viewEntryList->cnt; j++) {
2451 			ret = addViewEntryIoctl(fd, &guidList->guid[i],
2452 			    &viewEntryList->ve[j]);
2453 			if (ret != STMF_STATUS_SUCCESS) {
2454 				goto out;
2455 			}
2456 		}
2457 	}
2458 
2459 	/* get the list of providers that have data */
2460 	ret = psGetProviderDataList(&providerList);
2461 	switch (ret) {
2462 		case STMF_PS_SUCCESS:
2463 			ret = STMF_STATUS_SUCCESS;
2464 			break;
2465 		case STMF_PS_ERROR_NOT_FOUND:
2466 			ret = STMF_ERROR_NOT_FOUND;
2467 			break;
2468 		case STMF_PS_ERROR_BUSY:
2469 			ret = STMF_ERROR_BUSY;
2470 			break;
2471 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
2472 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
2473 			break;
2474 		case STMF_PS_ERROR_VERSION_MISMATCH:
2475 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
2476 			break;
2477 		default:
2478 			ret = STMF_STATUS_ERROR;
2479 			break;
2480 	}
2481 	if (ret != STMF_STATUS_SUCCESS) {
2482 		goto out;
2483 	}
2484 
2485 	for (i = 0; i < providerList->cnt; i++) {
2486 		providerType = providerList->provider[i].providerType;
2487 		ret = psGetProviderData(providerList->provider[i].name,
2488 		    &nvl, providerType, NULL);
2489 		switch (ret) {
2490 			case STMF_PS_SUCCESS:
2491 				ret = STMF_STATUS_SUCCESS;
2492 				break;
2493 			case STMF_PS_ERROR_NOT_FOUND:
2494 				ret = STMF_ERROR_NOT_FOUND;
2495 				break;
2496 			case STMF_PS_ERROR_BUSY:
2497 				ret = STMF_ERROR_BUSY;
2498 				break;
2499 			case STMF_PS_ERROR_SERVICE_NOT_FOUND:
2500 				ret = STMF_ERROR_SERVICE_NOT_FOUND;
2501 				break;
2502 			case STMF_PS_ERROR_VERSION_MISMATCH:
2503 				ret = STMF_ERROR_SERVICE_DATA_VERSION;
2504 				break;
2505 			default:
2506 				ret = STMF_STATUS_ERROR;
2507 				break;
2508 		}
2509 		if (ret != STMF_STATUS_SUCCESS) {
2510 			goto out;
2511 		}
2512 
2513 		/* call setProviderData */
2514 		ret = setProviderData(fd, providerList->provider[i].name, nvl,
2515 		    providerType);
2516 		switch (ret) {
2517 			case STMF_PS_SUCCESS:
2518 				ret = STMF_STATUS_SUCCESS;
2519 				break;
2520 			case STMF_PS_ERROR_NOT_FOUND:
2521 				ret = STMF_ERROR_NOT_FOUND;
2522 				break;
2523 			case STMF_PS_ERROR_BUSY:
2524 				ret = STMF_ERROR_BUSY;
2525 				break;
2526 			case STMF_PS_ERROR_SERVICE_NOT_FOUND:
2527 				ret = STMF_ERROR_SERVICE_NOT_FOUND;
2528 				break;
2529 			case STMF_PS_ERROR_VERSION_MISMATCH:
2530 				ret = STMF_ERROR_SERVICE_DATA_VERSION;
2531 				break;
2532 			default:
2533 				ret = STMF_STATUS_ERROR;
2534 				break;
2535 		}
2536 		if (ret != STMF_STATUS_SUCCESS) {
2537 			goto out;
2538 		}
2539 
2540 		nvlist_free(nvl);
2541 		nvl = NULL;
2542 	}
2543 out:
2544 	if (groupList != NULL) {
2545 		free(groupList);
2546 	}
2547 	if (guidList != NULL) {
2548 		free(guidList);
2549 	}
2550 	if (viewEntryList != NULL) {
2551 		free(viewEntryList);
2552 	}
2553 	if (nvl != NULL) {
2554 		nvlist_free(nvl);
2555 	}
2556 	return (ret);
2557 }
2558 
2559 /*
2560  * stmfLoadConfig
2561  *
2562  * Purpose - load the configuration data from smf into stmf
2563  *
2564  */
2565 int
2566 stmfLoadConfig(void)
2567 {
2568 	int ret;
2569 	int fd;
2570 	stmf_state_desc_t stmfStateSet;
2571 	stmfState state;
2572 
2573 
2574 	/* Check to ensure service exists */
2575 	if (psCheckService() != STMF_STATUS_SUCCESS) {
2576 		return (STMF_ERROR_SERVICE_NOT_FOUND);
2577 	}
2578 
2579 	ret = stmfGetState(&state);
2580 	if (ret == STMF_STATUS_SUCCESS) {
2581 		if (state.operationalState != STMF_SERVICE_STATE_OFFLINE) {
2582 			return (STMF_ERROR_SERVICE_ONLINE);
2583 		}
2584 	} else {
2585 		return (STMF_STATUS_ERROR);
2586 	}
2587 
2588 
2589 	stmfStateSet.state = STMF_STATE_OFFLINE;
2590 	stmfStateSet.config_state = STMF_CONFIG_INIT;
2591 
2592 	/*
2593 	 * Open control node for stmf
2594 	 */
2595 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
2596 		return (ret);
2597 
2598 	ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE);
2599 	if (ret != STMF_STATUS_SUCCESS) {
2600 		goto done;
2601 	}
2602 
2603 	/* Load the persistent configuration data */
2604 	ret = loadStore(fd);
2605 	if (ret != 0) {
2606 		goto done;
2607 	}
2608 
2609 	stmfStateSet.state = STMF_STATE_OFFLINE;
2610 	stmfStateSet.config_state = STMF_CONFIG_INIT_DONE;
2611 
2612 done:
2613 	if (ret == STMF_STATUS_SUCCESS) {
2614 		ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE);
2615 	}
2616 	(void) close(fd);
2617 	return (ret);
2618 }
2619 
2620 /*
2621  * getStmfState
2622  *
2623  * stmfState - pointer to stmf_state_desc_t structure. Will contain the state
2624  *             information of the stmf service on success.
2625  */
2626 static int
2627 getStmfState(stmf_state_desc_t *stmfState)
2628 {
2629 	int ret = STMF_STATUS_SUCCESS;
2630 	int fd;
2631 	int ioctlRet;
2632 	stmf_iocdata_t stmfIoctl;
2633 
2634 	/*
2635 	 * Open control node for stmf
2636 	 */
2637 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
2638 		return (ret);
2639 
2640 	bzero(&stmfIoctl, sizeof (stmfIoctl));
2641 	/*
2642 	 * Issue ioctl to get the stmf state
2643 	 */
2644 	stmfIoctl.stmf_version = STMF_VERSION_1;
2645 	stmfIoctl.stmf_ibuf_size = sizeof (stmf_state_desc_t);
2646 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)stmfState;
2647 	stmfIoctl.stmf_obuf_size = sizeof (stmf_state_desc_t);
2648 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)stmfState;
2649 	ioctlRet = ioctl(fd, STMF_IOCTL_GET_STMF_STATE, &stmfIoctl);
2650 
2651 	(void) close(fd);
2652 
2653 	if (ioctlRet != 0) {
2654 		switch (errno) {
2655 			case EBUSY:
2656 				ret = STMF_ERROR_BUSY;
2657 				break;
2658 			case EPERM:
2659 			case EACCES:
2660 				ret = STMF_ERROR_PERM;
2661 				break;
2662 			default:
2663 				syslog(LOG_DEBUG,
2664 				    "getStmfState:ioctl errno(%d)", errno);
2665 				ret = STMF_STATUS_ERROR;
2666 				break;
2667 		}
2668 	}
2669 	return (ret);
2670 }
2671 
2672 
2673 /*
2674  * setStmfState
2675  *
2676  * stmfState - pointer to caller set state structure
2677  * objectType - one of:
2678  *		LOGICAL_UNIT_TYPE
2679  *		TARGET_TYPE
2680  *		STMF_SERVICE_TYPE
2681  */
2682 static int
2683 setStmfState(int fd, stmf_state_desc_t *stmfState, int objectType)
2684 {
2685 	int ret = STMF_STATUS_SUCCESS;
2686 	int ioctlRet;
2687 	int cmd;
2688 	stmf_iocdata_t stmfIoctl;
2689 
2690 	switch (objectType) {
2691 		case LOGICAL_UNIT_TYPE:
2692 			cmd = STMF_IOCTL_SET_LU_STATE;
2693 			break;
2694 		case TARGET_TYPE:
2695 			cmd = STMF_IOCTL_SET_TARGET_PORT_STATE;
2696 			break;
2697 		case STMF_SERVICE_TYPE:
2698 			cmd = STMF_IOCTL_SET_STMF_STATE;
2699 			break;
2700 		default:
2701 			ret = STMF_STATUS_ERROR;
2702 			goto done;
2703 	}
2704 
2705 	bzero(&stmfIoctl, sizeof (stmfIoctl));
2706 	/*
2707 	 * Issue ioctl to set the stmf state
2708 	 */
2709 	stmfIoctl.stmf_version = STMF_VERSION_1;
2710 	stmfIoctl.stmf_ibuf_size = sizeof (stmf_state_desc_t);
2711 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)stmfState;
2712 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
2713 	if (ioctlRet != 0) {
2714 		switch (errno) {
2715 			case EBUSY:
2716 				ret = STMF_ERROR_BUSY;
2717 				break;
2718 			case EACCES:
2719 				ret = STMF_ERROR_PERM;
2720 				break;
2721 			case ENOENT:
2722 				ret = STMF_ERROR_NOT_FOUND;
2723 				break;
2724 			default:
2725 				syslog(LOG_DEBUG,
2726 				    "setStmfState:ioctl errno(%d)", errno);
2727 				ret = STMF_STATUS_ERROR;
2728 				break;
2729 		}
2730 	}
2731 done:
2732 	return (ret);
2733 }
2734 
2735 /*
2736  * stmfOnline
2737  *
2738  * Purpose: Online stmf service
2739  *
2740  */
2741 int
2742 stmfOnline(void)
2743 {
2744 	int ret;
2745 	int fd;
2746 	stmfState state;
2747 	stmf_state_desc_t iState;
2748 
2749 	ret = stmfGetState(&state);
2750 	if (ret == STMF_STATUS_SUCCESS) {
2751 		if (state.operationalState == STMF_SERVICE_STATE_ONLINE) {
2752 			return (STMF_ERROR_SERVICE_ONLINE);
2753 		}
2754 	} else {
2755 		return (STMF_STATUS_ERROR);
2756 	}
2757 	iState.state = STMF_STATE_ONLINE;
2758 	iState.config_state = STMF_CONFIG_NONE;
2759 	/*
2760 	 * Open control node for stmf
2761 	 * to make call to setStmfState()
2762 	 */
2763 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
2764 		return (ret);
2765 	ret = setStmfState(fd, &iState, STMF_SERVICE_TYPE);
2766 	(void) close(fd);
2767 	return (ret);
2768 }
2769 
2770 /*
2771  * stmfOffline
2772  *
2773  * Purpose: Offline stmf service
2774  *
2775  */
2776 int
2777 stmfOffline(void)
2778 {
2779 	int ret;
2780 	int fd;
2781 	stmfState state;
2782 	stmf_state_desc_t iState;
2783 
2784 	ret = stmfGetState(&state);
2785 	if (ret == STMF_STATUS_SUCCESS) {
2786 		if (state.operationalState == STMF_SERVICE_STATE_OFFLINE) {
2787 			return (STMF_ERROR_SERVICE_OFFLINE);
2788 		}
2789 	} else {
2790 		return (STMF_STATUS_ERROR);
2791 	}
2792 	iState.state = STMF_STATE_OFFLINE;
2793 	iState.config_state = STMF_CONFIG_NONE;
2794 
2795 	/*
2796 	 * Open control node for stmf
2797 	 * to make call to setStmfState()
2798 	 */
2799 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
2800 		return (ret);
2801 	ret = setStmfState(fd, &iState, STMF_SERVICE_TYPE);
2802 	(void) close(fd);
2803 	return (ret);
2804 }
2805 
2806 
2807 /*
2808  * stmfOfflineTarget
2809  *
2810  * Purpose: Change state of target to offline
2811  *
2812  * devid - devid of the target to offline
2813  */
2814 int
2815 stmfOfflineTarget(stmfDevid *devid)
2816 {
2817 	stmf_state_desc_t targetState;
2818 	int ret = STMF_STATUS_SUCCESS;
2819 	int fd;
2820 
2821 	if (devid == NULL) {
2822 		return (STMF_ERROR_INVALID_ARG);
2823 	}
2824 	bzero(&targetState, sizeof (targetState));
2825 
2826 	targetState.state = STMF_STATE_OFFLINE;
2827 	targetState.ident[IDENT_LENGTH_BYTE] = devid->identLength;
2828 	bcopy(&(devid->ident), &targetState.ident[IDENT_LENGTH_BYTE + 1],
2829 	    devid->identLength);
2830 	/*
2831 	 * Open control node for stmf
2832 	 * to make call to setStmfState()
2833 	 */
2834 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
2835 		return (ret);
2836 	ret = setStmfState(fd, &targetState, TARGET_TYPE);
2837 	(void) close(fd);
2838 	return (ret);
2839 }
2840 
2841 /*
2842  * stmfOfflineLogicalUnit
2843  *
2844  * Purpose: Change state of logical unit to offline
2845  *
2846  * lu - guid of the logical unit to offline
2847  */
2848 int
2849 stmfOfflineLogicalUnit(stmfGuid *lu)
2850 {
2851 	stmf_state_desc_t luState;
2852 	int ret = STMF_STATUS_SUCCESS;
2853 	int fd;
2854 
2855 	if (lu == NULL) {
2856 		return (STMF_ERROR_INVALID_ARG);
2857 	}
2858 
2859 	bzero(&luState, sizeof (luState));
2860 
2861 	luState.state = STMF_STATE_OFFLINE;
2862 	bcopy(lu, &luState.ident, sizeof (stmfGuid));
2863 	/*
2864 	 * Open control node for stmf
2865 	 * to make call to setStmfState()
2866 	 */
2867 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
2868 		return (ret);
2869 	ret = setStmfState(fd, &luState, LOGICAL_UNIT_TYPE);
2870 	(void) close(fd);
2871 	return (ret);
2872 }
2873 
2874 /*
2875  * stmfOnlineTarget
2876  *
2877  * Purpose: Change state of target to online
2878  *
2879  * devid - devid of the target to online
2880  */
2881 int
2882 stmfOnlineTarget(stmfDevid *devid)
2883 {
2884 	stmf_state_desc_t targetState;
2885 	int ret = STMF_STATUS_SUCCESS;
2886 	int fd;
2887 
2888 	if (devid == NULL) {
2889 		return (STMF_ERROR_INVALID_ARG);
2890 	}
2891 	bzero(&targetState, sizeof (targetState));
2892 
2893 	targetState.state = STMF_STATE_ONLINE;
2894 	targetState.ident[IDENT_LENGTH_BYTE] = devid->identLength;
2895 	bcopy(&(devid->ident), &targetState.ident[IDENT_LENGTH_BYTE + 1],
2896 	    devid->identLength);
2897 	/*
2898 	 * Open control node for stmf
2899 	 * to make call to setStmfState()
2900 	 */
2901 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
2902 		return (ret);
2903 	ret = setStmfState(fd, &targetState, TARGET_TYPE);
2904 	(void) close(fd);
2905 	return (ret);
2906 }
2907 
2908 /*
2909  * stmfOnlineLogicalUnit
2910  *
2911  * Purpose: Change state of logical unit to online
2912  *
2913  * lu - guid of the logical unit to online
2914  */
2915 int
2916 stmfOnlineLogicalUnit(stmfGuid *lu)
2917 {
2918 	stmf_state_desc_t luState;
2919 	int ret = STMF_STATUS_SUCCESS;
2920 	int fd;
2921 
2922 	if (lu == NULL) {
2923 		return (STMF_ERROR_INVALID_ARG);
2924 	}
2925 
2926 	bzero(&luState, sizeof (luState));
2927 
2928 	luState.state = STMF_STATE_ONLINE;
2929 	bcopy(lu, &luState.ident, sizeof (stmfGuid));
2930 	/*
2931 	 * Open control node for stmf
2932 	 * to make call to setStmfState()
2933 	 */
2934 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
2935 		return (ret);
2936 	ret = setStmfState(fd, &luState, LOGICAL_UNIT_TYPE);
2937 	(void) close(fd);
2938 	return (ret);
2939 }
2940 
2941 /*
2942  * stmfRemoveFromHostGroup
2943  *
2944  * Purpose: Removes an initiator from an initiator group
2945  *
2946  * hostGroupName - name of an initiator group
2947  * hostName - name of host group member to remove
2948  */
2949 int
2950 stmfRemoveFromHostGroup(stmfGroupName *hostGroupName, stmfDevid *hostName)
2951 {
2952 	int ret;
2953 	int fd;
2954 
2955 	if (hostGroupName == NULL ||
2956 	    (strnlen((char *)hostGroupName, sizeof (stmfGroupName))
2957 	    == sizeof (stmfGroupName)) || hostName == NULL) {
2958 		return (STMF_ERROR_INVALID_ARG);
2959 	}
2960 
2961 	/* call init */
2962 	ret = initializeConfig();
2963 	if (ret != STMF_STATUS_SUCCESS) {
2964 		return (ret);
2965 	}
2966 
2967 	/*
2968 	 * Open control node for stmf
2969 	 */
2970 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
2971 		return (ret);
2972 
2973 	if ((ret = groupMemberIoctl(fd, STMF_IOCTL_REMOVE_HG_ENTRY,
2974 	    hostGroupName, hostName)) != STMF_STATUS_SUCCESS) {
2975 		goto done;
2976 	}
2977 
2978 	ret = psRemoveHostGroupMember((char *)hostGroupName,
2979 	    (char *)hostName->ident);
2980 	switch (ret) {
2981 		case STMF_PS_SUCCESS:
2982 			ret = STMF_STATUS_SUCCESS;
2983 			break;
2984 		case STMF_PS_ERROR_MEMBER_NOT_FOUND:
2985 			ret = STMF_ERROR_MEMBER_NOT_FOUND;
2986 			break;
2987 		case STMF_PS_ERROR_GROUP_NOT_FOUND:
2988 			ret = STMF_ERROR_GROUP_NOT_FOUND;
2989 			break;
2990 		case STMF_PS_ERROR_BUSY:
2991 			ret = STMF_ERROR_BUSY;
2992 			break;
2993 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
2994 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
2995 			break;
2996 		case STMF_PS_ERROR_VERSION_MISMATCH:
2997 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
2998 			break;
2999 		default:
3000 			syslog(LOG_DEBUG,
3001 			    "stmfRemoveFromHostGroup"
3002 			    "psRemoveHostGroupMember:error(%d)", ret);
3003 			ret = STMF_STATUS_ERROR;
3004 			break;
3005 	}
3006 
3007 done:
3008 	(void) close(fd);
3009 	return (ret);
3010 }
3011 
3012 /*
3013  * stmfRemoveFromTargetGroup
3014  *
3015  * Purpose: Removes a local port from a local port group
3016  *
3017  * targetGroupName - name of a target group
3018  * targetName - name of target to remove
3019  */
3020 int
3021 stmfRemoveFromTargetGroup(stmfGroupName *targetGroupName, stmfDevid *targetName)
3022 {
3023 	int ret;
3024 	int fd;
3025 
3026 	if (targetGroupName == NULL ||
3027 	    (strnlen((char *)targetGroupName, sizeof (stmfGroupName))
3028 	    == sizeof (stmfGroupName)) || targetName == NULL) {
3029 		return (STMF_ERROR_INVALID_ARG);
3030 	}
3031 
3032 	/* call init */
3033 	ret = initializeConfig();
3034 	if (ret != STMF_STATUS_SUCCESS) {
3035 		return (ret);
3036 	}
3037 
3038 	/*
3039 	 * Open control node for stmf
3040 	 */
3041 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
3042 		return (ret);
3043 
3044 	if ((ret = groupMemberIoctl(fd, STMF_IOCTL_REMOVE_TG_ENTRY,
3045 	    targetGroupName, targetName)) != STMF_STATUS_SUCCESS) {
3046 		goto done;
3047 	}
3048 
3049 	ret = psRemoveTargetGroupMember((char *)targetGroupName,
3050 	    (char *)targetName->ident);
3051 	switch (ret) {
3052 		case STMF_PS_SUCCESS:
3053 			ret = STMF_STATUS_SUCCESS;
3054 			break;
3055 		case STMF_PS_ERROR_MEMBER_NOT_FOUND:
3056 			ret = STMF_ERROR_MEMBER_NOT_FOUND;
3057 			break;
3058 		case STMF_PS_ERROR_GROUP_NOT_FOUND:
3059 			ret = STMF_ERROR_GROUP_NOT_FOUND;
3060 			break;
3061 		case STMF_PS_ERROR_BUSY:
3062 			ret = STMF_ERROR_BUSY;
3063 			break;
3064 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
3065 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
3066 			break;
3067 		case STMF_PS_ERROR_VERSION_MISMATCH:
3068 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
3069 			break;
3070 		default:
3071 			syslog(LOG_DEBUG,
3072 			    "stmfRemoveFromTargetGroup"
3073 			    "psRemoveTargetGroupMember:error(%d)", ret);
3074 			ret = STMF_STATUS_ERROR;
3075 			break;
3076 	}
3077 
3078 done:
3079 	(void) close(fd);
3080 	return (ret);
3081 }
3082 
3083 /*
3084  * stmfRemoveViewEntry
3085  *
3086  * Purpose: Removes a view entry from a logical unit
3087  *
3088  * lu - guid of lu for which view entry is being removed
3089  * viewEntryIndex - index of view entry to remove
3090  *
3091  */
3092 int
3093 stmfRemoveViewEntry(stmfGuid *lu, uint32_t viewEntryIndex)
3094 {
3095 	int ret = STMF_STATUS_SUCCESS;
3096 	int fd;
3097 	int ioctlRet;
3098 	stmf_iocdata_t stmfIoctl;
3099 	stmf_view_op_entry_t ioctlViewEntry;
3100 
3101 	if (lu == NULL) {
3102 		return (STMF_ERROR_INVALID_ARG);
3103 	}
3104 
3105 	/* call init */
3106 	ret = initializeConfig();
3107 	if (ret != STMF_STATUS_SUCCESS) {
3108 		return (ret);
3109 	}
3110 
3111 	/*
3112 	 * Open control node for stmf
3113 	 */
3114 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
3115 		return (ret);
3116 
3117 	bzero(&ioctlViewEntry, sizeof (ioctlViewEntry));
3118 	ioctlViewEntry.ve_ndx_valid = B_TRUE;
3119 	ioctlViewEntry.ve_ndx = viewEntryIndex;
3120 	bcopy(lu, &ioctlViewEntry.ve_guid, sizeof (stmfGuid));
3121 
3122 	bzero(&stmfIoctl, sizeof (stmfIoctl));
3123 	/*
3124 	 * Issue ioctl to add to the view entry
3125 	 */
3126 	stmfIoctl.stmf_version = STMF_VERSION_1;
3127 	stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry);
3128 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry;
3129 	ioctlRet = ioctl(fd, STMF_IOCTL_REMOVE_VIEW_ENTRY, &stmfIoctl);
3130 	if (ioctlRet != 0) {
3131 		switch (errno) {
3132 			case EBUSY:
3133 				ret = STMF_ERROR_BUSY;
3134 				break;
3135 			case EACCES:
3136 				switch (stmfIoctl.stmf_error) {
3137 					case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
3138 						ret = STMF_ERROR_CONFIG_NONE;
3139 						break;
3140 					default:
3141 						ret = STMF_ERROR_PERM;
3142 						break;
3143 				}
3144 				break;
3145 			case ENODEV:
3146 			case ENOENT:
3147 				ret = STMF_ERROR_NOT_FOUND;
3148 				break;
3149 			default:
3150 				syslog(LOG_DEBUG,
3151 				    "stmfRemoveViewEntry:ioctl errno(%d)",
3152 				    errno);
3153 				ret = STMF_STATUS_ERROR;
3154 				break;
3155 		}
3156 		goto done;
3157 	}
3158 
3159 	ret = psRemoveViewEntry(lu, viewEntryIndex);
3160 	switch (ret) {
3161 		case STMF_PS_SUCCESS:
3162 			ret = STMF_STATUS_SUCCESS;
3163 			break;
3164 		case STMF_PS_ERROR_NOT_FOUND:
3165 			ret = STMF_ERROR_NOT_FOUND;
3166 			break;
3167 		case STMF_PS_ERROR_BUSY:
3168 			ret = STMF_ERROR_BUSY;
3169 			break;
3170 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
3171 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
3172 			break;
3173 		case STMF_PS_ERROR_VERSION_MISMATCH:
3174 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
3175 			break;
3176 		default:
3177 			syslog(LOG_DEBUG,
3178 			    "stmfRemoveViewEntry" "psRemoveViewEntry:error(%d)",
3179 			    ret);
3180 			ret = STMF_STATUS_ERROR;
3181 			break;
3182 	}
3183 
3184 done:
3185 	(void) close(fd);
3186 	return (ret);
3187 }
3188 
3189 /*
3190  * stmfSetProviderData
3191  *
3192  * Purpose: set the provider data
3193  *
3194  * providerName - unique name of provider
3195  * nvl - nvlist to set
3196  * providerType - type of provider for which to set data
3197  *		STMF_LU_PROVIDER_TYPE
3198  *		STMF_PORT_PROVIDER_TYPE
3199  */
3200 int
3201 stmfSetProviderData(char *providerName, nvlist_t *nvl, int providerType)
3202 {
3203 	return (stmfSetProviderDataProt(providerName, nvl, providerType,
3204 	    NULL));
3205 }
3206 
3207 /*
3208  * stmfSetProviderDataProt
3209  *
3210  * Purpose: set the provider data
3211  *
3212  * providerName - unique name of provider
3213  * nvl - nvlist to set
3214  * providerType - type of provider for which to set data
3215  *		STMF_LU_PROVIDER_TYPE
3216  *		STMF_PORT_PROVIDER_TYPE
3217  * setToken - Stale data token returned in the stmfGetProviderDataProt()
3218  *	      call or NULL.
3219  */
3220 int
3221 stmfSetProviderDataProt(char *providerName, nvlist_t *nvl, int providerType,
3222     uint64_t *setToken)
3223 {
3224 	int ret;
3225 	int fd;
3226 
3227 	if (providerName == NULL || nvl == NULL) {
3228 		return (STMF_ERROR_INVALID_ARG);
3229 	}
3230 
3231 	if (providerType != STMF_LU_PROVIDER_TYPE &&
3232 	    providerType != STMF_PORT_PROVIDER_TYPE) {
3233 		return (STMF_ERROR_INVALID_ARG);
3234 	}
3235 
3236 	/* call init */
3237 	ret = initializeConfig();
3238 	if (ret != STMF_STATUS_SUCCESS) {
3239 		return (ret);
3240 	}
3241 
3242 	/*
3243 	 * Open control node for stmf
3244 	 */
3245 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
3246 		return (ret);
3247 
3248 	ret = setProviderData(fd, providerName, nvl, providerType);
3249 
3250 	(void) close(fd);
3251 
3252 	if (ret != STMF_STATUS_SUCCESS) {
3253 		goto done;
3254 	}
3255 
3256 	/* setting driver provider data successful. Now persist it */
3257 	ret = psSetProviderData(providerName, nvl, providerType, setToken);
3258 	switch (ret) {
3259 		case STMF_PS_SUCCESS:
3260 			ret = STMF_STATUS_SUCCESS;
3261 			break;
3262 		case STMF_PS_ERROR_EXISTS:
3263 			ret = STMF_ERROR_EXISTS;
3264 			break;
3265 		case STMF_PS_ERROR_BUSY:
3266 			ret = STMF_ERROR_BUSY;
3267 			break;
3268 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
3269 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
3270 			break;
3271 		case STMF_PS_ERROR_VERSION_MISMATCH:
3272 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
3273 			break;
3274 		case STMF_PS_ERROR_PROV_DATA_STALE:
3275 			ret = STMF_ERROR_PROV_DATA_STALE;
3276 			break;
3277 		default:
3278 			syslog(LOG_DEBUG,
3279 			    "stmfSetProviderData"
3280 			    "psSetProviderData:error(%d)", ret);
3281 			ret = STMF_STATUS_ERROR;
3282 			break;
3283 	}
3284 
3285 done:
3286 	return (ret);
3287 }
3288 
3289 /*
3290  * setProviderData
3291  *
3292  * Purpose: set the provider data
3293  *
3294  * providerName - unique name of provider
3295  * nvl - nvlist to set
3296  * providerType - logical unit or port provider
3297  */
3298 static int
3299 setProviderData(int fd, char *providerName, nvlist_t *nvl, int providerType)
3300 {
3301 	int ret = STMF_STATUS_SUCCESS;
3302 	int ioctlRet;
3303 	size_t nvlistEncodedSize;
3304 	stmf_ppioctl_data_t *ppi = NULL;
3305 	char *allocatedNvBuffer;
3306 	stmf_iocdata_t stmfIoctl;
3307 
3308 	if (providerName == NULL) {
3309 		return (STMF_ERROR_INVALID_ARG);
3310 	}
3311 
3312 	/* get size of encoded nvlist */
3313 	if (nvlist_size(nvl, &nvlistEncodedSize, NV_ENCODE_XDR) != 0) {
3314 		return (STMF_STATUS_ERROR);
3315 	}
3316 
3317 	/* allocate memory for ioctl */
3318 	ppi = (stmf_ppioctl_data_t *)calloc(1, nvlistEncodedSize +
3319 	    sizeof (stmf_ppioctl_data_t));
3320 	if (ppi == NULL) {
3321 		return (STMF_ERROR_NOMEM);
3322 	}
3323 
3324 	allocatedNvBuffer = (char *)&ppi->ppi_data;
3325 	if (nvlist_pack(nvl, &allocatedNvBuffer, &nvlistEncodedSize,
3326 	    NV_ENCODE_XDR, 0) != 0) {
3327 		return (STMF_STATUS_ERROR);
3328 	}
3329 
3330 	/* set provider name and provider type */
3331 	(void) strncpy(ppi->ppi_name, providerName, sizeof (ppi->ppi_name));
3332 	switch (providerType) {
3333 		case STMF_LU_PROVIDER_TYPE:
3334 			ppi->ppi_lu_provider = 1;
3335 			break;
3336 		case STMF_PORT_PROVIDER_TYPE:
3337 			ppi->ppi_port_provider = 1;
3338 			break;
3339 		default:
3340 			return (STMF_ERROR_INVALID_ARG);
3341 	}
3342 
3343 	/* set the size of the ioctl data to packed data size */
3344 	ppi->ppi_data_size = nvlistEncodedSize;
3345 
3346 	bzero(&stmfIoctl, sizeof (stmfIoctl));
3347 
3348 	stmfIoctl.stmf_version = STMF_VERSION_1;
3349 	/*
3350 	 * Subtracting 8 from the size as that is the size of the last member
3351 	 * of the structure where the packed data resides
3352 	 */
3353 	stmfIoctl.stmf_ibuf_size = nvlistEncodedSize +
3354 	    sizeof (stmf_ppioctl_data_t) - 8;
3355 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)ppi;
3356 	ioctlRet = ioctl(fd, STMF_IOCTL_LOAD_PP_DATA, &stmfIoctl);
3357 	if (ioctlRet != 0) {
3358 		switch (errno) {
3359 			case EBUSY:
3360 				ret = STMF_ERROR_BUSY;
3361 				break;
3362 			case EACCES:
3363 				ret = STMF_ERROR_PERM;
3364 				break;
3365 			default:
3366 				syslog(LOG_DEBUG,
3367 				    "setProviderData:ioctl errno(%d)", errno);
3368 				ret = STMF_STATUS_ERROR;
3369 				break;
3370 		}
3371 		if (ret != STMF_STATUS_SUCCESS)
3372 			goto done;
3373 	}
3374 
3375 done:
3376 	free(ppi);
3377 	return (ret);
3378 }
3379