xref: /illumos-gate/usr/src/lib/libstmf/common/stmf.c (revision 6cefaae1e90a413ba01560575bb3998e1a3df40e)
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;
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 	fTargetList = (slist_target_port_t *)calloc(1, fTargetListSize);
1675 	if (fTargetList == NULL) {
1676 		goto done;
1677 	}
1678 
1679 	bzero(&stmfIoctl, sizeof (stmfIoctl));
1680 	/*
1681 	 * Issue ioctl to add to the host group
1682 	 */
1683 	stmfIoctl.stmf_version = STMF_VERSION_1;
1684 	stmfIoctl.stmf_obuf_size = fTargetListSize;
1685 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fTargetList;
1686 	ioctlRet = ioctl(fd, STMF_IOCTL_TARGET_PORT_LIST, &stmfIoctl);
1687 	if (ioctlRet != 0) {
1688 		switch (errno) {
1689 			case EBUSY:
1690 				ret = STMF_ERROR_BUSY;
1691 				break;
1692 			case EACCES:
1693 				ret = STMF_ERROR_PERM;
1694 				break;
1695 			default:
1696 				syslog(LOG_DEBUG,
1697 				    "stmfGetTargetList:ioctl errno(%d)", errno);
1698 				ret = STMF_STATUS_ERROR;
1699 				break;
1700 		}
1701 		goto done;
1702 	}
1703 	/*
1704 	 * Check whether input buffer was large enough
1705 	 */
1706 	if (stmfIoctl.stmf_obuf_max_nentries > MAX_TARGET_PORT) {
1707 		fTargetListSize = stmfIoctl.stmf_obuf_max_nentries *
1708 		    sizeof (slist_target_port_t);
1709 		fTargetList = realloc(fTargetList, fTargetListSize);
1710 		if (fTargetList == NULL) {
1711 			return (STMF_ERROR_NOMEM);
1712 		}
1713 		stmfIoctl.stmf_obuf_size = fTargetListSize;
1714 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fTargetList;
1715 		ioctlRet = ioctl(fd, STMF_IOCTL_TARGET_PORT_LIST,
1716 		    &stmfIoctl);
1717 		if (ioctlRet != 0) {
1718 			switch (errno) {
1719 				case EBUSY:
1720 					ret = STMF_ERROR_BUSY;
1721 					break;
1722 				case EACCES:
1723 					ret = STMF_ERROR_PERM;
1724 					break;
1725 				default:
1726 					syslog(LOG_DEBUG,
1727 					    "stmfGetTargetList:ioctl errno(%d)",
1728 					    errno);
1729 					ret = STMF_STATUS_ERROR;
1730 					break;
1731 			}
1732 			goto done;
1733 		}
1734 	}
1735 
1736 	*targetList = (stmfDevidList *)calloc(1,
1737 	    stmfIoctl.stmf_obuf_max_nentries * sizeof (stmfDevid) +
1738 	    sizeof (stmfDevidList));
1739 
1740 	(*targetList)->cnt = stmfIoctl.stmf_obuf_max_nentries;
1741 	for (i = 0; i < stmfIoctl.stmf_obuf_max_nentries; i++, fTargetList++) {
1742 		(*targetList)->devid[i].identLength =
1743 		    fTargetList->target[IDENT_LENGTH_BYTE];
1744 		bcopy(&fTargetList->target[IDENT_LENGTH_BYTE + 1],
1745 		    &(*targetList)->devid[i].ident,
1746 		    fTargetList->target[IDENT_LENGTH_BYTE]);
1747 	}
1748 
1749 done:
1750 	(void) close(fd);
1751 	free(fTargetList);
1752 	return (ret);
1753 }
1754 
1755 /*
1756  * stmfGetTargetProperties
1757  *
1758  * Purpose:  Retrieves the properties for a logical unit
1759  *
1760  * devid - devid of the target for which to retrieve properties
1761  * targetProps - pointer to an stmfTargetProperties structure.
1762  *		On success, it contains the target properties for
1763  *		the specified devid.
1764  */
1765 int
1766 stmfGetTargetProperties(stmfDevid *devid, stmfTargetProperties *targetProps)
1767 {
1768 	int ret = STMF_STATUS_SUCCESS;
1769 	int fd;
1770 	int ioctlRet;
1771 	stmf_iocdata_t stmfIoctl;
1772 	sioc_target_port_props_t targetProperties;
1773 
1774 	if (devid == NULL || targetProps == NULL) {
1775 		return (STMF_ERROR_INVALID_ARG);
1776 	}
1777 
1778 	/* call init */
1779 	ret = initializeConfig();
1780 	if (ret != STMF_STATUS_SUCCESS) {
1781 		return (ret);
1782 	}
1783 
1784 	/*
1785 	 * Open control node for stmf
1786 	 */
1787 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
1788 		return (ret);
1789 
1790 	targetProperties.tgt_id[IDENT_LENGTH_BYTE] = devid->identLength;
1791 	bcopy(&(devid->ident), &targetProperties.tgt_id[IDENT_LENGTH_BYTE + 1],
1792 	    devid->identLength);
1793 
1794 	bzero(&stmfIoctl, sizeof (stmfIoctl));
1795 	/*
1796 	 * Issue ioctl to add to the host group
1797 	 */
1798 	stmfIoctl.stmf_version = STMF_VERSION_1;
1799 	stmfIoctl.stmf_ibuf_size = sizeof (targetProperties.tgt_id);
1800 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&targetProperties.tgt_id;
1801 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&targetProperties;
1802 	stmfIoctl.stmf_obuf_size = sizeof (targetProperties);
1803 	ioctlRet = ioctl(fd, STMF_IOCTL_GET_TARGET_PORT_PROPERTIES,
1804 	    &stmfIoctl);
1805 	if (ioctlRet != 0) {
1806 		switch (errno) {
1807 			case EBUSY:
1808 				ret = STMF_ERROR_BUSY;
1809 				break;
1810 			case EACCES:
1811 				ret = STMF_ERROR_PERM;
1812 				break;
1813 			case ENOENT:
1814 				ret = STMF_ERROR_NOT_FOUND;
1815 				break;
1816 			default:
1817 				syslog(LOG_DEBUG,
1818 				    "stmfGetTargetProperties:ioctl errno(%d)",
1819 				    errno);
1820 				ret = STMF_STATUS_ERROR;
1821 				break;
1822 		}
1823 		goto done;
1824 	}
1825 
1826 	bcopy(targetProperties.tgt_provider_name, targetProps->providerName,
1827 	    sizeof (targetProperties.tgt_provider_name));
1828 	if (targetProperties.tgt_state == STMF_STATE_ONLINE) {
1829 		targetProps->status = STMF_TARGET_PORT_ONLINE;
1830 	} else if (targetProperties.tgt_state == STMF_STATE_OFFLINE) {
1831 		targetProps->status = STMF_TARGET_PORT_OFFLINE;
1832 	} else if (targetProperties.tgt_state == STMF_STATE_ONLINING) {
1833 		targetProps->status = STMF_TARGET_PORT_ONLINING;
1834 	} else if (targetProperties.tgt_state == STMF_STATE_OFFLINING) {
1835 		targetProps->status = STMF_TARGET_PORT_OFFLINING;
1836 	}
1837 	bcopy(targetProperties.tgt_alias, targetProps->alias,
1838 	    sizeof (targetProps->alias));
1839 done:
1840 	(void) close(fd);
1841 	return (ret);
1842 }
1843 
1844 /*
1845  * stmfGetLogicalUnitList
1846  *
1847  * Purpose: Retrieves list of logical unit Object IDs
1848  *
1849  * luList - pointer to a pointer to a stmfGuidList structure. On success,
1850  *          it contains the list of logical unit guids.
1851  *
1852  */
1853 int
1854 stmfGetLogicalUnitList(stmfGuidList **luList)
1855 {
1856 	int ret;
1857 	int fd;
1858 	int ioctlRet;
1859 	int cmd = STMF_IOCTL_LU_LIST;
1860 	int i, k;
1861 	stmf_iocdata_t stmfIoctl;
1862 	/* framework lu list */
1863 	slist_lu_t *fLuList;
1864 	/* persistent store lu list */
1865 	stmfGuidList *sLuList = NULL;
1866 	int finalListSize = 0;
1867 	int newAllocSize;
1868 	uint32_t fLuListSize;
1869 	uint32_t endList;
1870 
1871 	if (luList == NULL) {
1872 		return (STMF_ERROR_INVALID_ARG);
1873 	}
1874 
1875 	/* call init */
1876 	ret = initializeConfig();
1877 	if (ret != STMF_STATUS_SUCCESS) {
1878 		return (ret);
1879 	}
1880 
1881 	/*
1882 	 * Open control node for stmf
1883 	 */
1884 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
1885 		return (ret);
1886 
1887 	/*
1888 	 * Allocate ioctl input buffer
1889 	 */
1890 	fLuListSize = MAX_LU;
1891 	fLuListSize = fLuListSize * (sizeof (slist_lu_t));
1892 	fLuList = (slist_lu_t *)calloc(1, fLuListSize);
1893 	if (fLuList == NULL) {
1894 		return (STMF_ERROR_NOMEM);
1895 	}
1896 
1897 	bzero(&stmfIoctl, sizeof (stmfIoctl));
1898 	/*
1899 	 * Issue ioctl to get the LU list
1900 	 */
1901 	stmfIoctl.stmf_version = STMF_VERSION_1;
1902 	stmfIoctl.stmf_obuf_size = fLuListSize;
1903 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fLuList;
1904 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
1905 	if (ioctlRet != 0) {
1906 		switch (errno) {
1907 			case EBUSY:
1908 				ret = STMF_ERROR_BUSY;
1909 				break;
1910 			case EACCES:
1911 				ret = STMF_ERROR_PERM;
1912 				break;
1913 			default:
1914 				syslog(LOG_DEBUG,
1915 				    "stmfGetLogicalUnitList:ioctl errno(%d)",
1916 				    errno);
1917 				ret = STMF_STATUS_ERROR;
1918 				break;
1919 		}
1920 		goto done;
1921 	}
1922 	/*
1923 	 * Check whether input buffer was large enough
1924 	 */
1925 	if (stmfIoctl.stmf_obuf_max_nentries > MAX_LU) {
1926 		fLuListSize = stmfIoctl.stmf_obuf_max_nentries *
1927 		    sizeof (slist_lu_t);
1928 		fLuList = realloc(fLuList, fLuListSize);
1929 		if (fLuList == NULL) {
1930 			return (STMF_ERROR_NOMEM);
1931 		}
1932 		stmfIoctl.stmf_obuf_size = fLuListSize;
1933 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fLuList;
1934 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
1935 		if (ioctlRet != 0) {
1936 			switch (errno) {
1937 				case EBUSY:
1938 					ret = STMF_ERROR_BUSY;
1939 					break;
1940 				case EACCES:
1941 					ret = STMF_ERROR_PERM;
1942 					break;
1943 				default:
1944 					syslog(LOG_DEBUG,
1945 					    "stmfGetLogicalUnitList:"
1946 					    "ioctl errno(%d)", errno);
1947 					ret = STMF_STATUS_ERROR;
1948 					break;
1949 			}
1950 			goto done;
1951 		}
1952 	}
1953 
1954 	ret = psGetLogicalUnitList(&sLuList);
1955 	switch (ret) {
1956 		case STMF_PS_SUCCESS:
1957 			ret = STMF_STATUS_SUCCESS;
1958 			break;
1959 		case STMF_PS_ERROR_BUSY:
1960 			ret = STMF_ERROR_BUSY;
1961 			break;
1962 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
1963 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
1964 			break;
1965 		case STMF_PS_ERROR_VERSION_MISMATCH:
1966 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
1967 			break;
1968 		default:
1969 			syslog(LOG_DEBUG,
1970 			    "stmfGetLogicalUnitList:psGetLogicalUnitList"
1971 			    ":error(%d)", ret);
1972 			ret = STMF_STATUS_ERROR;
1973 			break;
1974 	}
1975 	if (ret != STMF_STATUS_SUCCESS) {
1976 		goto done;
1977 	}
1978 
1979 	/*
1980 	 * 2 lists must be merged
1981 	 * reallocate the store list to add the list from the
1982 	 * framework
1983 	 */
1984 	newAllocSize = sLuList->cnt * sizeof (stmfGuid) + sizeof (stmfGuidList)
1985 	    + stmfIoctl.stmf_obuf_nentries * sizeof (stmfGuid);
1986 
1987 	sLuList = realloc(sLuList, newAllocSize);
1988 	if (sLuList == NULL) {
1989 		ret = STMF_ERROR_NOMEM;
1990 		goto done;
1991 	}
1992 
1993 	/*
1994 	 * add list from ioctl. Start from end of list retrieved from store.
1995 	 */
1996 	endList = sLuList->cnt + stmfIoctl.stmf_obuf_nentries;
1997 	for (k = 0, i = sLuList->cnt; i < endList; i++, k++) {
1998 		bcopy(&fLuList[k].lu_guid, sLuList->guid[i].guid,
1999 		    sizeof (stmfGuid));
2000 	}
2001 	sLuList->cnt = endList;
2002 
2003 	/*
2004 	 * sort the list for merging
2005 	 */
2006 	qsort((void *)&(sLuList->guid[0]), sLuList->cnt,
2007 	    sizeof (stmfGuid), guidCompare);
2008 
2009 	/*
2010 	 * get final list count
2011 	 */
2012 	for (i = 0; i < sLuList->cnt; i++) {
2013 		if ((i + 1) <= sLuList->cnt) {
2014 			if (bcmp(sLuList->guid[i].guid, sLuList->guid[i+1].guid,
2015 			    sizeof (stmfGuid)) == 0) {
2016 				continue;
2017 			}
2018 		}
2019 		finalListSize++;
2020 	}
2021 
2022 	/*
2023 	 * allocate caller's buffer with the final size
2024 	 */
2025 	*luList = (stmfGuidList *)calloc(1, sizeof (stmfGuidList) +
2026 	    finalListSize * sizeof (stmfGuid));
2027 	if (*luList == NULL) {
2028 		ret = STMF_ERROR_NOMEM;
2029 		goto done;
2030 	}
2031 
2032 	/*
2033 	 * copy guids to caller's buffer
2034 	 */
2035 	for (k = 0, i = 0; i < sLuList->cnt; i++) {
2036 		if ((i + 1) <= sLuList->cnt) {
2037 			if (bcmp(sLuList->guid[i].guid, sLuList->guid[i+1].guid,
2038 			    sizeof (stmfGuid)) == 0) {
2039 				continue;
2040 			}
2041 		}
2042 		bcopy(&(sLuList->guid[i].guid), (*luList)->guid[k++].guid,
2043 		    sizeof (stmfGuid));
2044 	}
2045 
2046 	(*luList)->cnt = finalListSize;
2047 
2048 done:
2049 	(void) close(fd);
2050 	/*
2051 	 * free internal buffers
2052 	 */
2053 	free(fLuList);
2054 	free(sLuList);
2055 	return (ret);
2056 }
2057 
2058 /*
2059  * stmfGetLogicalUnitProperties
2060  *
2061  * Purpose:  Retrieves the properties for a logical unit
2062  *
2063  * lu - guid of the logical unit for which to retrieve properties
2064  * stmfLuProps - pointer to an stmfLogicalUnitProperties structure. On success,
2065  *               it contains the logical unit properties for the specified guid.
2066  */
2067 int
2068 stmfGetLogicalUnitProperties(stmfGuid *lu, stmfLogicalUnitProperties *luProps)
2069 {
2070 	int ret = STMF_STATUS_SUCCESS;
2071 	int stmfRet;
2072 	int fd;
2073 	int ioctlRet;
2074 	int cmd = STMF_IOCTL_GET_LU_PROPERTIES;
2075 	stmfViewEntryList *viewEntryList = NULL;
2076 	stmf_iocdata_t stmfIoctl;
2077 	sioc_lu_props_t fLuProps;
2078 
2079 	if (luProps == NULL || luProps == NULL) {
2080 		ret = STMF_ERROR_INVALID_ARG;
2081 	}
2082 
2083 	bzero(luProps, sizeof (stmfLogicalUnitProperties));
2084 
2085 	/* call init */
2086 	ret = initializeConfig();
2087 	if (ret != STMF_STATUS_SUCCESS) {
2088 		return (ret);
2089 	}
2090 
2091 	/*
2092 	 * Open control node for stmf
2093 	 */
2094 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
2095 		return (ret);
2096 
2097 	bzero(&stmfIoctl, sizeof (stmfIoctl));
2098 	/*
2099 	 * Issue ioctl to add to the host group
2100 	 */
2101 	stmfIoctl.stmf_version = STMF_VERSION_1;
2102 	stmfIoctl.stmf_ibuf_size = sizeof (stmfGuid);
2103 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)lu;
2104 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&fLuProps;
2105 	stmfIoctl.stmf_obuf_size = sizeof (fLuProps);
2106 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
2107 	if (ioctlRet != 0) {
2108 		switch (errno) {
2109 			case EBUSY:
2110 				ret = STMF_ERROR_BUSY;
2111 				break;
2112 			case EACCES:
2113 				ret = STMF_ERROR_PERM;
2114 				break;
2115 			case ENOENT:
2116 				stmfRet = stmfGetViewEntryList(lu,
2117 				    &viewEntryList);
2118 				if (stmfRet == STMF_STATUS_SUCCESS) {
2119 					luProps->status =
2120 					    STMF_LOGICAL_UNIT_UNREGISTERED;
2121 					if (viewEntryList->cnt > 0) {
2122 						ret = STMF_STATUS_SUCCESS;
2123 					} else {
2124 						ret = STMF_ERROR_NOT_FOUND;
2125 					}
2126 				} else {
2127 					ret = STMF_ERROR_NOT_FOUND;
2128 				}
2129 				stmfFreeMemory(viewEntryList);
2130 				break;
2131 			default:
2132 				syslog(LOG_DEBUG,
2133 				    "stmfGetLogicalUnit:ioctl errno(%d)",
2134 				    errno);
2135 				ret = STMF_STATUS_ERROR;
2136 				break;
2137 		}
2138 		goto done;
2139 	}
2140 
2141 	bcopy(fLuProps.lu_provider_name, luProps->providerName,
2142 	    sizeof (fLuProps.lu_provider_name));
2143 	if (fLuProps.lu_state == STMF_STATE_ONLINE) {
2144 		luProps->status = STMF_LOGICAL_UNIT_ONLINE;
2145 	} else if (fLuProps.lu_state == STMF_STATE_OFFLINE) {
2146 		luProps->status = STMF_LOGICAL_UNIT_OFFLINE;
2147 	} else if (fLuProps.lu_state == STMF_STATE_ONLINING) {
2148 		luProps->status = STMF_LOGICAL_UNIT_ONLINING;
2149 	} else if (fLuProps.lu_state == STMF_STATE_OFFLINING) {
2150 		luProps->status = STMF_LOGICAL_UNIT_OFFLINING;
2151 	}
2152 	bcopy(fLuProps.lu_alias, luProps->alias, sizeof (luProps->alias));
2153 done:
2154 	(void) close(fd);
2155 	return (ret);
2156 }
2157 
2158 /*
2159  * stmfGetState
2160  *
2161  * Purpose: retrieve the current state of the stmf module
2162  *
2163  * state - pointer to stmfState structure allocated by the caller
2164  *         On success, contains the state of stmf
2165  */
2166 int
2167 stmfGetState(stmfState *state)
2168 {
2169 	int ret;
2170 	stmf_state_desc_t iState;
2171 
2172 	if (state == NULL) {
2173 		return (STMF_ERROR_INVALID_ARG);
2174 	}
2175 
2176 	ret = getStmfState(&iState);
2177 	if (ret != STMF_STATUS_SUCCESS) {
2178 		return (ret);
2179 	}
2180 	switch (iState.state) {
2181 		case STMF_STATE_ONLINE:
2182 			state->operationalState =
2183 			    STMF_SERVICE_STATE_ONLINE;
2184 			break;
2185 		case STMF_STATE_OFFLINE:
2186 			state->operationalState =
2187 			    STMF_SERVICE_STATE_OFFLINE;
2188 			break;
2189 		case STMF_STATE_ONLINING:
2190 			state->operationalState =
2191 			    STMF_SERVICE_STATE_ONLINING;
2192 			break;
2193 		case STMF_STATE_OFFLINING:
2194 			state->operationalState =
2195 			    STMF_SERVICE_STATE_OFFLINING;
2196 			break;
2197 		default:
2198 			state->operationalState =
2199 			    STMF_SERVICE_STATE_UNKNOWN;
2200 			break;
2201 	}
2202 	switch (iState.config_state) {
2203 		case STMF_CONFIG_NONE:
2204 			state->configState = STMF_CONFIG_STATE_NONE;
2205 			break;
2206 		case STMF_CONFIG_INIT:
2207 			state->configState = STMF_CONFIG_STATE_INIT;
2208 			break;
2209 		case STMF_CONFIG_INIT_DONE:
2210 			state->configState =
2211 			    STMF_CONFIG_STATE_INIT_DONE;
2212 			break;
2213 		default:
2214 			state->configState =
2215 			    STMF_CONFIG_STATE_UNKNOWN;
2216 			break;
2217 	}
2218 	return (STMF_STATUS_SUCCESS);
2219 }
2220 
2221 /*
2222  * stmfGetViewEntryList
2223  *
2224  * Purpose: Retrieves the list of view entries for the specified
2225  *          logical unit.
2226  *
2227  * lu - the guid of the logical unit for which to retrieve the view entry list
2228  * viewEntryList - a pointer to a pointer to a stmfViewEntryList structure. On
2229  *                 success, contains the list of view entries.
2230  */
2231 int
2232 stmfGetViewEntryList(stmfGuid *lu, stmfViewEntryList **viewEntryList)
2233 {
2234 	int ret;
2235 
2236 	if (lu == NULL || viewEntryList == NULL) {
2237 		return (STMF_ERROR_INVALID_ARG);
2238 	}
2239 
2240 	ret = psGetViewEntryList(lu, viewEntryList);
2241 	switch (ret) {
2242 		case STMF_PS_SUCCESS:
2243 			ret = STMF_STATUS_SUCCESS;
2244 			break;
2245 		case STMF_PS_ERROR_NOT_FOUND:
2246 			ret = STMF_ERROR_NOT_FOUND;
2247 			break;
2248 		case STMF_PS_ERROR_BUSY:
2249 			ret = STMF_ERROR_BUSY;
2250 			break;
2251 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
2252 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
2253 			break;
2254 		case STMF_PS_ERROR_VERSION_MISMATCH:
2255 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
2256 			break;
2257 		default:
2258 			syslog(LOG_DEBUG,
2259 			    "stmfGetViewEntryList:error(%d)", ret);
2260 			ret = STMF_STATUS_ERROR;
2261 			break;
2262 	}
2263 
2264 	return (ret);
2265 }
2266 
2267 /*
2268  * loadHostGroups
2269  *
2270  * Purpose - issues the ioctl to load the host groups into stmf
2271  *
2272  * fd - file descriptor for the control node of stmf.
2273  * groupList - populated host group list
2274  */
2275 static int
2276 loadHostGroups(int fd, stmfGroupList *groupList)
2277 {
2278 	int i, j;
2279 	int ret = STMF_STATUS_SUCCESS;
2280 	stmfGroupProperties *groupProps = NULL;
2281 
2282 	for (i = 0; i < groupList->cnt; i++) {
2283 		if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_HOST_GROUP,
2284 		    &(groupList->name[i]))) != STMF_STATUS_SUCCESS) {
2285 			goto out;
2286 		}
2287 		ret = stmfGetHostGroupMembers(&(groupList->name[i]),
2288 		    &groupProps);
2289 		for (j = 0; j < groupProps->cnt; j++) {
2290 			if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_HG_ENTRY,
2291 			    &(groupList->name[i]), &(groupProps->name[j])))
2292 			    != STMF_STATUS_SUCCESS) {
2293 				goto out;
2294 			}
2295 		}
2296 	}
2297 
2298 
2299 out:
2300 	stmfFreeMemory(groupProps);
2301 	return (ret);
2302 }
2303 
2304 /*
2305  * loadTargetGroups
2306  *
2307  * Purpose - issues the ioctl to load the target groups into stmf
2308  *
2309  * fd - file descriptor for the control node of stmf.
2310  * groupList - populated target group list.
2311  */
2312 static int
2313 loadTargetGroups(int fd, stmfGroupList *groupList)
2314 {
2315 	int i, j;
2316 	int ret = STMF_STATUS_SUCCESS;
2317 	stmfGroupProperties *groupProps = NULL;
2318 
2319 	for (i = 0; i < groupList->cnt; i++) {
2320 		if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_TARGET_GROUP,
2321 		    &(groupList->name[i]))) != STMF_STATUS_SUCCESS) {
2322 			goto out;
2323 		}
2324 		ret = stmfGetTargetGroupMembers(&(groupList->name[i]),
2325 		    &groupProps);
2326 		for (j = 0; j < groupProps->cnt; j++) {
2327 			if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_TG_ENTRY,
2328 			    &(groupList->name[i]), &(groupProps->name[j])))
2329 			    != STMF_STATUS_SUCCESS) {
2330 				goto out;
2331 			}
2332 		}
2333 	}
2334 
2335 
2336 out:
2337 	stmfFreeMemory(groupProps);
2338 	return (ret);
2339 }
2340 
2341 
2342 /*
2343  * loadStore
2344  *
2345  * Purpose: Load the configuration data from the store
2346  *
2347  * First load the host groups and target groups, then the view entries
2348  * and finally the provider data
2349  *
2350  * fd - file descriptor of control node for stmf.
2351  */
2352 static int
2353 loadStore(int fd)
2354 {
2355 	int ret;
2356 	int i, j;
2357 	stmfGroupList *groupList = NULL;
2358 	stmfGuidList *guidList = NULL;
2359 	stmfViewEntryList *viewEntryList = NULL;
2360 	stmfProviderList *providerList = NULL;
2361 	int providerType;
2362 	nvlist_t *nvl = NULL;
2363 
2364 
2365 
2366 	/* load host groups */
2367 	ret = stmfGetHostGroupList(&groupList);
2368 	if (ret != STMF_STATUS_SUCCESS) {
2369 		return (ret);
2370 	}
2371 	ret = loadHostGroups(fd, groupList);
2372 	if (ret != STMF_STATUS_SUCCESS) {
2373 		goto out;
2374 	}
2375 
2376 	stmfFreeMemory(groupList);
2377 	groupList = NULL;
2378 
2379 	/* load target groups */
2380 	ret = stmfGetTargetGroupList(&groupList);
2381 	if (ret != STMF_STATUS_SUCCESS) {
2382 		goto out;
2383 	}
2384 	ret = loadTargetGroups(fd, groupList);
2385 	if (ret != STMF_STATUS_SUCCESS) {
2386 		goto out;
2387 	}
2388 
2389 	stmfFreeMemory(groupList);
2390 	groupList = NULL;
2391 
2392 	/* Get the guid list */
2393 	ret = psGetLogicalUnitList(&guidList);
2394 	switch (ret) {
2395 		case STMF_PS_SUCCESS:
2396 			ret = STMF_STATUS_SUCCESS;
2397 			break;
2398 		case STMF_PS_ERROR_NOT_FOUND:
2399 			ret = STMF_ERROR_NOT_FOUND;
2400 			break;
2401 		case STMF_PS_ERROR_BUSY:
2402 			ret = STMF_ERROR_BUSY;
2403 			break;
2404 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
2405 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
2406 			break;
2407 		case STMF_PS_ERROR_VERSION_MISMATCH:
2408 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
2409 			break;
2410 		default:
2411 			ret = STMF_STATUS_ERROR;
2412 			break;
2413 	}
2414 
2415 	if (ret != STMF_STATUS_SUCCESS) {
2416 		goto out;
2417 	}
2418 
2419 	/*
2420 	 * We have the guid list, now get the corresponding
2421 	 * view entries for each guid
2422 	 */
2423 	for (i = 0; i < guidList->cnt; i++) {
2424 		ret = psGetViewEntryList(&guidList->guid[i], &viewEntryList);
2425 		switch (ret) {
2426 			case STMF_PS_SUCCESS:
2427 				ret = STMF_STATUS_SUCCESS;
2428 				break;
2429 			case STMF_PS_ERROR_NOT_FOUND:
2430 				ret = STMF_ERROR_NOT_FOUND;
2431 				break;
2432 			case STMF_PS_ERROR_BUSY:
2433 				ret = STMF_ERROR_BUSY;
2434 				break;
2435 			case STMF_PS_ERROR_SERVICE_NOT_FOUND:
2436 				ret = STMF_ERROR_SERVICE_NOT_FOUND;
2437 				break;
2438 			case STMF_PS_ERROR_VERSION_MISMATCH:
2439 				ret = STMF_ERROR_SERVICE_DATA_VERSION;
2440 				break;
2441 			default:
2442 				ret = STMF_STATUS_ERROR;
2443 				break;
2444 		}
2445 		if (ret != STMF_STATUS_SUCCESS) {
2446 			goto out;
2447 		}
2448 		for (j = 0; j < viewEntryList->cnt; j++) {
2449 			ret = addViewEntryIoctl(fd, &guidList->guid[i],
2450 			    &viewEntryList->ve[j]);
2451 			if (ret != STMF_STATUS_SUCCESS) {
2452 				goto out;
2453 			}
2454 		}
2455 	}
2456 
2457 	/* get the list of providers that have data */
2458 	ret = psGetProviderDataList(&providerList);
2459 	switch (ret) {
2460 		case STMF_PS_SUCCESS:
2461 			ret = STMF_STATUS_SUCCESS;
2462 			break;
2463 		case STMF_PS_ERROR_NOT_FOUND:
2464 			ret = STMF_ERROR_NOT_FOUND;
2465 			break;
2466 		case STMF_PS_ERROR_BUSY:
2467 			ret = STMF_ERROR_BUSY;
2468 			break;
2469 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
2470 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
2471 			break;
2472 		case STMF_PS_ERROR_VERSION_MISMATCH:
2473 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
2474 			break;
2475 		default:
2476 			ret = STMF_STATUS_ERROR;
2477 			break;
2478 	}
2479 	if (ret != STMF_STATUS_SUCCESS) {
2480 		goto out;
2481 	}
2482 
2483 	for (i = 0; i < providerList->cnt; i++) {
2484 		providerType = providerList->provider[i].providerType;
2485 		ret = psGetProviderData(providerList->provider[i].name,
2486 		    &nvl, providerType, NULL);
2487 		switch (ret) {
2488 			case STMF_PS_SUCCESS:
2489 				ret = STMF_STATUS_SUCCESS;
2490 				break;
2491 			case STMF_PS_ERROR_NOT_FOUND:
2492 				ret = STMF_ERROR_NOT_FOUND;
2493 				break;
2494 			case STMF_PS_ERROR_BUSY:
2495 				ret = STMF_ERROR_BUSY;
2496 				break;
2497 			case STMF_PS_ERROR_SERVICE_NOT_FOUND:
2498 				ret = STMF_ERROR_SERVICE_NOT_FOUND;
2499 				break;
2500 			case STMF_PS_ERROR_VERSION_MISMATCH:
2501 				ret = STMF_ERROR_SERVICE_DATA_VERSION;
2502 				break;
2503 			default:
2504 				ret = STMF_STATUS_ERROR;
2505 				break;
2506 		}
2507 		if (ret != STMF_STATUS_SUCCESS) {
2508 			goto out;
2509 		}
2510 
2511 		/* call setProviderData */
2512 		ret = setProviderData(fd, providerList->provider[i].name, nvl,
2513 		    providerType);
2514 		switch (ret) {
2515 			case STMF_PS_SUCCESS:
2516 				ret = STMF_STATUS_SUCCESS;
2517 				break;
2518 			case STMF_PS_ERROR_NOT_FOUND:
2519 				ret = STMF_ERROR_NOT_FOUND;
2520 				break;
2521 			case STMF_PS_ERROR_BUSY:
2522 				ret = STMF_ERROR_BUSY;
2523 				break;
2524 			case STMF_PS_ERROR_SERVICE_NOT_FOUND:
2525 				ret = STMF_ERROR_SERVICE_NOT_FOUND;
2526 				break;
2527 			case STMF_PS_ERROR_VERSION_MISMATCH:
2528 				ret = STMF_ERROR_SERVICE_DATA_VERSION;
2529 				break;
2530 			default:
2531 				ret = STMF_STATUS_ERROR;
2532 				break;
2533 		}
2534 		if (ret != STMF_STATUS_SUCCESS) {
2535 			goto out;
2536 		}
2537 
2538 		nvlist_free(nvl);
2539 		nvl = NULL;
2540 	}
2541 out:
2542 	if (groupList != NULL) {
2543 		free(groupList);
2544 	}
2545 	if (guidList != NULL) {
2546 		free(guidList);
2547 	}
2548 	if (viewEntryList != NULL) {
2549 		free(viewEntryList);
2550 	}
2551 	if (nvl != NULL) {
2552 		nvlist_free(nvl);
2553 	}
2554 	return (ret);
2555 }
2556 
2557 /*
2558  * stmfLoadConfig
2559  *
2560  * Purpose - load the configuration data from smf into stmf
2561  *
2562  */
2563 int
2564 stmfLoadConfig(void)
2565 {
2566 	int ret;
2567 	int fd;
2568 	stmf_state_desc_t stmfStateSet;
2569 	stmfState state;
2570 
2571 
2572 	/* Check to ensure service exists */
2573 	if (psCheckService() != STMF_STATUS_SUCCESS) {
2574 		return (STMF_ERROR_SERVICE_NOT_FOUND);
2575 	}
2576 
2577 	ret = stmfGetState(&state);
2578 	if (ret == STMF_STATUS_SUCCESS) {
2579 		if (state.operationalState != STMF_SERVICE_STATE_OFFLINE) {
2580 			return (STMF_ERROR_SERVICE_ONLINE);
2581 		}
2582 	} else {
2583 		return (STMF_STATUS_ERROR);
2584 	}
2585 
2586 
2587 	stmfStateSet.state = STMF_STATE_OFFLINE;
2588 	stmfStateSet.config_state = STMF_CONFIG_INIT;
2589 
2590 	/*
2591 	 * Open control node for stmf
2592 	 */
2593 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
2594 		return (ret);
2595 
2596 	ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE);
2597 	if (ret != STMF_STATUS_SUCCESS) {
2598 		goto done;
2599 	}
2600 
2601 	/* Load the persistent configuration data */
2602 	ret = loadStore(fd);
2603 	if (ret != 0) {
2604 		goto done;
2605 	}
2606 
2607 	stmfStateSet.state = STMF_STATE_OFFLINE;
2608 	stmfStateSet.config_state = STMF_CONFIG_INIT_DONE;
2609 
2610 done:
2611 	if (ret == STMF_STATUS_SUCCESS) {
2612 		ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE);
2613 	}
2614 	(void) close(fd);
2615 	return (ret);
2616 }
2617 
2618 /*
2619  * getStmfState
2620  *
2621  * stmfState - pointer to stmf_state_desc_t structure. Will contain the state
2622  *             information of the stmf service on success.
2623  */
2624 static int
2625 getStmfState(stmf_state_desc_t *stmfState)
2626 {
2627 	int ret = STMF_STATUS_SUCCESS;
2628 	int fd;
2629 	int ioctlRet;
2630 	stmf_iocdata_t stmfIoctl;
2631 
2632 	/*
2633 	 * Open control node for stmf
2634 	 */
2635 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
2636 		return (ret);
2637 
2638 	bzero(&stmfIoctl, sizeof (stmfIoctl));
2639 	/*
2640 	 * Issue ioctl to get the stmf state
2641 	 */
2642 	stmfIoctl.stmf_version = STMF_VERSION_1;
2643 	stmfIoctl.stmf_ibuf_size = sizeof (stmf_state_desc_t);
2644 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)stmfState;
2645 	stmfIoctl.stmf_obuf_size = sizeof (stmf_state_desc_t);
2646 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)stmfState;
2647 	ioctlRet = ioctl(fd, STMF_IOCTL_GET_STMF_STATE, &stmfIoctl);
2648 
2649 	(void) close(fd);
2650 
2651 	if (ioctlRet != 0) {
2652 		switch (errno) {
2653 			case EBUSY:
2654 				ret = STMF_ERROR_BUSY;
2655 				break;
2656 			case EPERM:
2657 			case EACCES:
2658 				ret = STMF_ERROR_PERM;
2659 				break;
2660 			default:
2661 				syslog(LOG_DEBUG,
2662 				    "getStmfState:ioctl errno(%d)", errno);
2663 				ret = STMF_STATUS_ERROR;
2664 				break;
2665 		}
2666 	}
2667 	return (ret);
2668 }
2669 
2670 
2671 /*
2672  * setStmfState
2673  *
2674  * stmfState - pointer to caller set state structure
2675  * objectType - one of:
2676  *		LOGICAL_UNIT_TYPE
2677  *		TARGET_TYPE
2678  *		STMF_SERVICE_TYPE
2679  */
2680 static int
2681 setStmfState(int fd, stmf_state_desc_t *stmfState, int objectType)
2682 {
2683 	int ret = STMF_STATUS_SUCCESS;
2684 	int ioctlRet;
2685 	int cmd;
2686 	stmf_iocdata_t stmfIoctl;
2687 
2688 	switch (objectType) {
2689 		case LOGICAL_UNIT_TYPE:
2690 			cmd = STMF_IOCTL_SET_LU_STATE;
2691 			break;
2692 		case TARGET_TYPE:
2693 			cmd = STMF_IOCTL_SET_TARGET_PORT_STATE;
2694 			break;
2695 		case STMF_SERVICE_TYPE:
2696 			cmd = STMF_IOCTL_SET_STMF_STATE;
2697 			break;
2698 		default:
2699 			ret = STMF_STATUS_ERROR;
2700 			goto done;
2701 	}
2702 
2703 	bzero(&stmfIoctl, sizeof (stmfIoctl));
2704 	/*
2705 	 * Issue ioctl to set the stmf state
2706 	 */
2707 	stmfIoctl.stmf_version = STMF_VERSION_1;
2708 	stmfIoctl.stmf_ibuf_size = sizeof (stmf_state_desc_t);
2709 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)stmfState;
2710 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
2711 	if (ioctlRet != 0) {
2712 		switch (errno) {
2713 			case EBUSY:
2714 				ret = STMF_ERROR_BUSY;
2715 				break;
2716 			case EACCES:
2717 				ret = STMF_ERROR_PERM;
2718 				break;
2719 			case ENOENT:
2720 				ret = STMF_ERROR_NOT_FOUND;
2721 				break;
2722 			default:
2723 				syslog(LOG_DEBUG,
2724 				    "setStmfState:ioctl errno(%d)", errno);
2725 				ret = STMF_STATUS_ERROR;
2726 				break;
2727 		}
2728 	}
2729 done:
2730 	return (ret);
2731 }
2732 
2733 /*
2734  * stmfOnline
2735  *
2736  * Purpose: Online stmf service
2737  *
2738  */
2739 int
2740 stmfOnline(void)
2741 {
2742 	int ret;
2743 	int fd;
2744 	stmfState state;
2745 	stmf_state_desc_t iState;
2746 
2747 	ret = stmfGetState(&state);
2748 	if (ret == STMF_STATUS_SUCCESS) {
2749 		if (state.operationalState == STMF_SERVICE_STATE_ONLINE) {
2750 			return (STMF_ERROR_SERVICE_ONLINE);
2751 		}
2752 	} else {
2753 		return (STMF_STATUS_ERROR);
2754 	}
2755 	iState.state = STMF_STATE_ONLINE;
2756 	iState.config_state = STMF_CONFIG_NONE;
2757 	/*
2758 	 * Open control node for stmf
2759 	 * to make call to setStmfState()
2760 	 */
2761 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
2762 		return (ret);
2763 	ret = setStmfState(fd, &iState, STMF_SERVICE_TYPE);
2764 	(void) close(fd);
2765 	return (ret);
2766 }
2767 
2768 /*
2769  * stmfOffline
2770  *
2771  * Purpose: Offline stmf service
2772  *
2773  */
2774 int
2775 stmfOffline(void)
2776 {
2777 	int ret;
2778 	int fd;
2779 	stmfState state;
2780 	stmf_state_desc_t iState;
2781 
2782 	ret = stmfGetState(&state);
2783 	if (ret == STMF_STATUS_SUCCESS) {
2784 		if (state.operationalState == STMF_SERVICE_STATE_OFFLINE) {
2785 			return (STMF_ERROR_SERVICE_OFFLINE);
2786 		}
2787 	} else {
2788 		return (STMF_STATUS_ERROR);
2789 	}
2790 	iState.state = STMF_STATE_OFFLINE;
2791 	iState.config_state = STMF_CONFIG_NONE;
2792 
2793 	/*
2794 	 * Open control node for stmf
2795 	 * to make call to setStmfState()
2796 	 */
2797 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
2798 		return (ret);
2799 	ret = setStmfState(fd, &iState, STMF_SERVICE_TYPE);
2800 	(void) close(fd);
2801 	return (ret);
2802 }
2803 
2804 
2805 /*
2806  * stmfOfflineTarget
2807  *
2808  * Purpose: Change state of target to offline
2809  *
2810  * devid - devid of the target to offline
2811  */
2812 int
2813 stmfOfflineTarget(stmfDevid *devid)
2814 {
2815 	stmf_state_desc_t targetState;
2816 	int ret = STMF_STATUS_SUCCESS;
2817 	int fd;
2818 
2819 	if (devid == NULL) {
2820 		return (STMF_ERROR_INVALID_ARG);
2821 	}
2822 	bzero(&targetState, sizeof (targetState));
2823 
2824 	targetState.state = STMF_STATE_OFFLINE;
2825 	targetState.ident[IDENT_LENGTH_BYTE] = devid->identLength;
2826 	bcopy(&(devid->ident), &targetState.ident[IDENT_LENGTH_BYTE + 1],
2827 	    devid->identLength);
2828 	/*
2829 	 * Open control node for stmf
2830 	 * to make call to setStmfState()
2831 	 */
2832 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
2833 		return (ret);
2834 	ret = setStmfState(fd, &targetState, TARGET_TYPE);
2835 	(void) close(fd);
2836 	return (ret);
2837 }
2838 
2839 /*
2840  * stmfOfflineLogicalUnit
2841  *
2842  * Purpose: Change state of logical unit to offline
2843  *
2844  * lu - guid of the logical unit to offline
2845  */
2846 int
2847 stmfOfflineLogicalUnit(stmfGuid *lu)
2848 {
2849 	stmf_state_desc_t luState;
2850 	int ret = STMF_STATUS_SUCCESS;
2851 	int fd;
2852 
2853 	if (lu == NULL) {
2854 		return (STMF_ERROR_INVALID_ARG);
2855 	}
2856 
2857 	bzero(&luState, sizeof (luState));
2858 
2859 	luState.state = STMF_STATE_OFFLINE;
2860 	bcopy(lu, &luState.ident, sizeof (stmfGuid));
2861 	/*
2862 	 * Open control node for stmf
2863 	 * to make call to setStmfState()
2864 	 */
2865 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
2866 		return (ret);
2867 	ret = setStmfState(fd, &luState, LOGICAL_UNIT_TYPE);
2868 	(void) close(fd);
2869 	return (ret);
2870 }
2871 
2872 /*
2873  * stmfOnlineTarget
2874  *
2875  * Purpose: Change state of target to online
2876  *
2877  * devid - devid of the target to online
2878  */
2879 int
2880 stmfOnlineTarget(stmfDevid *devid)
2881 {
2882 	stmf_state_desc_t targetState;
2883 	int ret = STMF_STATUS_SUCCESS;
2884 	int fd;
2885 
2886 	if (devid == NULL) {
2887 		return (STMF_ERROR_INVALID_ARG);
2888 	}
2889 	bzero(&targetState, sizeof (targetState));
2890 
2891 	targetState.state = STMF_STATE_ONLINE;
2892 	targetState.ident[IDENT_LENGTH_BYTE] = devid->identLength;
2893 	bcopy(&(devid->ident), &targetState.ident[IDENT_LENGTH_BYTE + 1],
2894 	    devid->identLength);
2895 	/*
2896 	 * Open control node for stmf
2897 	 * to make call to setStmfState()
2898 	 */
2899 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
2900 		return (ret);
2901 	ret = setStmfState(fd, &targetState, TARGET_TYPE);
2902 	(void) close(fd);
2903 	return (ret);
2904 }
2905 
2906 /*
2907  * stmfOnlineLogicalUnit
2908  *
2909  * Purpose: Change state of logical unit to online
2910  *
2911  * lu - guid of the logical unit to online
2912  */
2913 int
2914 stmfOnlineLogicalUnit(stmfGuid *lu)
2915 {
2916 	stmf_state_desc_t luState;
2917 	int ret = STMF_STATUS_SUCCESS;
2918 	int fd;
2919 
2920 	if (lu == NULL) {
2921 		return (STMF_ERROR_INVALID_ARG);
2922 	}
2923 
2924 	bzero(&luState, sizeof (luState));
2925 
2926 	luState.state = STMF_STATE_ONLINE;
2927 	bcopy(lu, &luState.ident, sizeof (stmfGuid));
2928 	/*
2929 	 * Open control node for stmf
2930 	 * to make call to setStmfState()
2931 	 */
2932 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
2933 		return (ret);
2934 	ret = setStmfState(fd, &luState, LOGICAL_UNIT_TYPE);
2935 	(void) close(fd);
2936 	return (ret);
2937 }
2938 
2939 /*
2940  * stmfRemoveFromHostGroup
2941  *
2942  * Purpose: Removes an initiator from an initiator group
2943  *
2944  * hostGroupName - name of an initiator group
2945  * hostName - name of host group member to remove
2946  */
2947 int
2948 stmfRemoveFromHostGroup(stmfGroupName *hostGroupName, stmfDevid *hostName)
2949 {
2950 	int ret;
2951 	int fd;
2952 
2953 	if (hostGroupName == NULL ||
2954 	    (strnlen((char *)hostGroupName, sizeof (stmfGroupName))
2955 	    == sizeof (stmfGroupName)) || hostName == NULL) {
2956 		return (STMF_ERROR_INVALID_ARG);
2957 	}
2958 
2959 	/* call init */
2960 	ret = initializeConfig();
2961 	if (ret != STMF_STATUS_SUCCESS) {
2962 		return (ret);
2963 	}
2964 
2965 	/*
2966 	 * Open control node for stmf
2967 	 */
2968 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
2969 		return (ret);
2970 
2971 	if ((ret = groupMemberIoctl(fd, STMF_IOCTL_REMOVE_HG_ENTRY,
2972 	    hostGroupName, hostName)) != STMF_STATUS_SUCCESS) {
2973 		goto done;
2974 	}
2975 
2976 	ret = psRemoveHostGroupMember((char *)hostGroupName,
2977 	    (char *)hostName->ident);
2978 	switch (ret) {
2979 		case STMF_PS_SUCCESS:
2980 			ret = STMF_STATUS_SUCCESS;
2981 			break;
2982 		case STMF_PS_ERROR_MEMBER_NOT_FOUND:
2983 			ret = STMF_ERROR_MEMBER_NOT_FOUND;
2984 			break;
2985 		case STMF_PS_ERROR_GROUP_NOT_FOUND:
2986 			ret = STMF_ERROR_GROUP_NOT_FOUND;
2987 			break;
2988 		case STMF_PS_ERROR_BUSY:
2989 			ret = STMF_ERROR_BUSY;
2990 			break;
2991 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
2992 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
2993 			break;
2994 		case STMF_PS_ERROR_VERSION_MISMATCH:
2995 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
2996 			break;
2997 		default:
2998 			syslog(LOG_DEBUG,
2999 			    "stmfRemoveFromHostGroup"
3000 			    "psRemoveHostGroupMember:error(%d)", ret);
3001 			ret = STMF_STATUS_ERROR;
3002 			break;
3003 	}
3004 
3005 done:
3006 	(void) close(fd);
3007 	return (ret);
3008 }
3009 
3010 /*
3011  * stmfRemoveFromTargetGroup
3012  *
3013  * Purpose: Removes a local port from a local port group
3014  *
3015  * targetGroupName - name of a target group
3016  * targetName - name of target to remove
3017  */
3018 int
3019 stmfRemoveFromTargetGroup(stmfGroupName *targetGroupName, stmfDevid *targetName)
3020 {
3021 	int ret;
3022 	int fd;
3023 
3024 	if (targetGroupName == NULL ||
3025 	    (strnlen((char *)targetGroupName, sizeof (stmfGroupName))
3026 	    == sizeof (stmfGroupName)) || targetName == NULL) {
3027 		return (STMF_ERROR_INVALID_ARG);
3028 	}
3029 
3030 	/* call init */
3031 	ret = initializeConfig();
3032 	if (ret != STMF_STATUS_SUCCESS) {
3033 		return (ret);
3034 	}
3035 
3036 	/*
3037 	 * Open control node for stmf
3038 	 */
3039 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
3040 		return (ret);
3041 
3042 	if ((ret = groupMemberIoctl(fd, STMF_IOCTL_REMOVE_TG_ENTRY,
3043 	    targetGroupName, targetName)) != STMF_STATUS_SUCCESS) {
3044 		goto done;
3045 	}
3046 
3047 	ret = psRemoveTargetGroupMember((char *)targetGroupName,
3048 	    (char *)targetName->ident);
3049 	switch (ret) {
3050 		case STMF_PS_SUCCESS:
3051 			ret = STMF_STATUS_SUCCESS;
3052 			break;
3053 		case STMF_PS_ERROR_MEMBER_NOT_FOUND:
3054 			ret = STMF_ERROR_MEMBER_NOT_FOUND;
3055 			break;
3056 		case STMF_PS_ERROR_GROUP_NOT_FOUND:
3057 			ret = STMF_ERROR_GROUP_NOT_FOUND;
3058 			break;
3059 		case STMF_PS_ERROR_BUSY:
3060 			ret = STMF_ERROR_BUSY;
3061 			break;
3062 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
3063 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
3064 			break;
3065 		case STMF_PS_ERROR_VERSION_MISMATCH:
3066 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
3067 			break;
3068 		default:
3069 			syslog(LOG_DEBUG,
3070 			    "stmfRemoveFromTargetGroup"
3071 			    "psRemoveTargetGroupMember:error(%d)", ret);
3072 			ret = STMF_STATUS_ERROR;
3073 			break;
3074 	}
3075 
3076 done:
3077 	(void) close(fd);
3078 	return (ret);
3079 }
3080 
3081 /*
3082  * stmfRemoveViewEntry
3083  *
3084  * Purpose: Removes a view entry from a logical unit
3085  *
3086  * lu - guid of lu for which view entry is being removed
3087  * viewEntryIndex - index of view entry to remove
3088  *
3089  */
3090 int
3091 stmfRemoveViewEntry(stmfGuid *lu, uint32_t viewEntryIndex)
3092 {
3093 	int ret = STMF_STATUS_SUCCESS;
3094 	int fd;
3095 	int ioctlRet;
3096 	stmf_iocdata_t stmfIoctl;
3097 	stmf_view_op_entry_t ioctlViewEntry;
3098 
3099 	if (lu == NULL) {
3100 		return (STMF_ERROR_INVALID_ARG);
3101 	}
3102 
3103 	/* call init */
3104 	ret = initializeConfig();
3105 	if (ret != STMF_STATUS_SUCCESS) {
3106 		return (ret);
3107 	}
3108 
3109 	/*
3110 	 * Open control node for stmf
3111 	 */
3112 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
3113 		return (ret);
3114 
3115 	bzero(&ioctlViewEntry, sizeof (ioctlViewEntry));
3116 	ioctlViewEntry.ve_ndx_valid = B_TRUE;
3117 	ioctlViewEntry.ve_ndx = viewEntryIndex;
3118 	bcopy(lu, &ioctlViewEntry.ve_guid, sizeof (stmfGuid));
3119 
3120 	bzero(&stmfIoctl, sizeof (stmfIoctl));
3121 	/*
3122 	 * Issue ioctl to add to the view entry
3123 	 */
3124 	stmfIoctl.stmf_version = STMF_VERSION_1;
3125 	stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry);
3126 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry;
3127 	ioctlRet = ioctl(fd, STMF_IOCTL_REMOVE_VIEW_ENTRY, &stmfIoctl);
3128 	if (ioctlRet != 0) {
3129 		switch (errno) {
3130 			case EBUSY:
3131 				ret = STMF_ERROR_BUSY;
3132 				break;
3133 			case EACCES:
3134 				switch (stmfIoctl.stmf_error) {
3135 					case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
3136 						ret = STMF_ERROR_CONFIG_NONE;
3137 						break;
3138 					default:
3139 						ret = STMF_ERROR_PERM;
3140 						break;
3141 				}
3142 				break;
3143 			case ENODEV:
3144 			case ENOENT:
3145 				ret = STMF_ERROR_NOT_FOUND;
3146 				break;
3147 			default:
3148 				syslog(LOG_DEBUG,
3149 				    "stmfRemoveViewEntry:ioctl errno(%d)",
3150 				    errno);
3151 				ret = STMF_STATUS_ERROR;
3152 				break;
3153 		}
3154 		goto done;
3155 	}
3156 
3157 	ret = psRemoveViewEntry(lu, viewEntryIndex);
3158 	switch (ret) {
3159 		case STMF_PS_SUCCESS:
3160 			ret = STMF_STATUS_SUCCESS;
3161 			break;
3162 		case STMF_PS_ERROR_NOT_FOUND:
3163 			ret = STMF_ERROR_NOT_FOUND;
3164 			break;
3165 		case STMF_PS_ERROR_BUSY:
3166 			ret = STMF_ERROR_BUSY;
3167 			break;
3168 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
3169 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
3170 			break;
3171 		case STMF_PS_ERROR_VERSION_MISMATCH:
3172 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
3173 			break;
3174 		default:
3175 			syslog(LOG_DEBUG,
3176 			    "stmfRemoveViewEntry" "psRemoveViewEntry:error(%d)",
3177 			    ret);
3178 			ret = STMF_STATUS_ERROR;
3179 			break;
3180 	}
3181 
3182 done:
3183 	(void) close(fd);
3184 	return (ret);
3185 }
3186 
3187 /*
3188  * stmfSetProviderData
3189  *
3190  * Purpose: set the provider data
3191  *
3192  * providerName - unique name of provider
3193  * nvl - nvlist to set
3194  * providerType - type of provider for which to set data
3195  *		STMF_LU_PROVIDER_TYPE
3196  *		STMF_PORT_PROVIDER_TYPE
3197  */
3198 int
3199 stmfSetProviderData(char *providerName, nvlist_t *nvl, int providerType)
3200 {
3201 	return (stmfSetProviderDataProt(providerName, nvl, providerType,
3202 	    NULL));
3203 }
3204 
3205 /*
3206  * stmfSetProviderDataProt
3207  *
3208  * Purpose: set the provider data
3209  *
3210  * providerName - unique name of provider
3211  * nvl - nvlist to set
3212  * providerType - type of provider for which to set data
3213  *		STMF_LU_PROVIDER_TYPE
3214  *		STMF_PORT_PROVIDER_TYPE
3215  * setToken - Stale data token returned in the stmfGetProviderDataProt()
3216  *	      call or NULL.
3217  */
3218 int
3219 stmfSetProviderDataProt(char *providerName, nvlist_t *nvl, int providerType,
3220     uint64_t *setToken)
3221 {
3222 	int ret;
3223 	int fd;
3224 
3225 	if (providerName == NULL || nvl == NULL) {
3226 		return (STMF_ERROR_INVALID_ARG);
3227 	}
3228 
3229 	if (providerType != STMF_LU_PROVIDER_TYPE &&
3230 	    providerType != STMF_PORT_PROVIDER_TYPE) {
3231 		return (STMF_ERROR_INVALID_ARG);
3232 	}
3233 
3234 	/* call init */
3235 	ret = initializeConfig();
3236 	if (ret != STMF_STATUS_SUCCESS) {
3237 		return (ret);
3238 	}
3239 
3240 	/*
3241 	 * Open control node for stmf
3242 	 */
3243 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
3244 		return (ret);
3245 
3246 	ret = setProviderData(fd, providerName, nvl, providerType);
3247 
3248 	(void) close(fd);
3249 
3250 	if (ret != STMF_STATUS_SUCCESS) {
3251 		goto done;
3252 	}
3253 
3254 	/* setting driver provider data successful. Now persist it */
3255 	ret = psSetProviderData(providerName, nvl, providerType, setToken);
3256 	switch (ret) {
3257 		case STMF_PS_SUCCESS:
3258 			ret = STMF_STATUS_SUCCESS;
3259 			break;
3260 		case STMF_PS_ERROR_EXISTS:
3261 			ret = STMF_ERROR_EXISTS;
3262 			break;
3263 		case STMF_PS_ERROR_BUSY:
3264 			ret = STMF_ERROR_BUSY;
3265 			break;
3266 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
3267 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
3268 			break;
3269 		case STMF_PS_ERROR_VERSION_MISMATCH:
3270 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
3271 			break;
3272 		case STMF_PS_ERROR_PROV_DATA_STALE:
3273 			ret = STMF_ERROR_PROV_DATA_STALE;
3274 			break;
3275 		default:
3276 			syslog(LOG_DEBUG,
3277 			    "stmfSetProviderData"
3278 			    "psSetProviderData:error(%d)", ret);
3279 			ret = STMF_STATUS_ERROR;
3280 			break;
3281 	}
3282 
3283 done:
3284 	return (ret);
3285 }
3286 
3287 /*
3288  * setProviderData
3289  *
3290  * Purpose: set the provider data
3291  *
3292  * providerName - unique name of provider
3293  * nvl - nvlist to set
3294  * providerType - logical unit or port provider
3295  */
3296 static int
3297 setProviderData(int fd, char *providerName, nvlist_t *nvl, int providerType)
3298 {
3299 	int ret = STMF_STATUS_SUCCESS;
3300 	int ioctlRet;
3301 	size_t nvlistEncodedSize;
3302 	stmf_ppioctl_data_t *ppi = NULL;
3303 	char *allocatedNvBuffer;
3304 	stmf_iocdata_t stmfIoctl;
3305 
3306 	if (providerName == NULL) {
3307 		return (STMF_ERROR_INVALID_ARG);
3308 	}
3309 
3310 	/* get size of encoded nvlist */
3311 	if (nvlist_size(nvl, &nvlistEncodedSize, NV_ENCODE_XDR) != 0) {
3312 		return (STMF_STATUS_ERROR);
3313 	}
3314 
3315 	/* allocate memory for ioctl */
3316 	ppi = (stmf_ppioctl_data_t *)calloc(1, nvlistEncodedSize +
3317 	    sizeof (stmf_ppioctl_data_t));
3318 	if (ppi == NULL) {
3319 		return (STMF_ERROR_NOMEM);
3320 	}
3321 
3322 	allocatedNvBuffer = (char *)&ppi->ppi_data;
3323 	if (nvlist_pack(nvl, &allocatedNvBuffer, &nvlistEncodedSize,
3324 	    NV_ENCODE_XDR, 0) != 0) {
3325 		return (STMF_STATUS_ERROR);
3326 	}
3327 
3328 	/* set provider name and provider type */
3329 	(void) strncpy(ppi->ppi_name, providerName, sizeof (ppi->ppi_name));
3330 	switch (providerType) {
3331 		case STMF_LU_PROVIDER_TYPE:
3332 			ppi->ppi_lu_provider = 1;
3333 			break;
3334 		case STMF_PORT_PROVIDER_TYPE:
3335 			ppi->ppi_port_provider = 1;
3336 			break;
3337 		default:
3338 			return (STMF_ERROR_INVALID_ARG);
3339 	}
3340 
3341 	/* set the size of the ioctl data to packed data size */
3342 	ppi->ppi_data_size = nvlistEncodedSize;
3343 
3344 	bzero(&stmfIoctl, sizeof (stmfIoctl));
3345 
3346 	stmfIoctl.stmf_version = STMF_VERSION_1;
3347 	/*
3348 	 * Subtracting 8 from the size as that is the size of the last member
3349 	 * of the structure where the packed data resides
3350 	 */
3351 	stmfIoctl.stmf_ibuf_size = nvlistEncodedSize +
3352 	    sizeof (stmf_ppioctl_data_t) - 8;
3353 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)ppi;
3354 	ioctlRet = ioctl(fd, STMF_IOCTL_LOAD_PP_DATA, &stmfIoctl);
3355 	if (ioctlRet != 0) {
3356 		switch (errno) {
3357 			case EBUSY:
3358 				ret = STMF_ERROR_BUSY;
3359 				break;
3360 			case EACCES:
3361 				ret = STMF_ERROR_PERM;
3362 				break;
3363 			default:
3364 				syslog(LOG_DEBUG,
3365 				    "setProviderData:ioctl errno(%d)", errno);
3366 				ret = STMF_STATUS_ERROR;
3367 				break;
3368 		}
3369 		if (ret != STMF_STATUS_SUCCESS)
3370 			goto done;
3371 	}
3372 
3373 done:
3374 	free(ppi);
3375 	return (ret);
3376 }
3377