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.
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.
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]
22 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2012 Milan Jurik. All rights reserved.
30 #include <sys/types.h>
38 #include <libnvpair.h>
42 #include <netinet/in.h>
47 #include <libstmf_impl.h>
48 #include <sys/stmf_ioctl.h>
49 #include <sys/stmf_sbd_ioctl.h>
50 #include <sys/pppt_ioctl.h>
53 #define STMF_PATH "/devices/pseudo/stmf@0:admin"
54 #define SBD_PATH "/devices/pseudo/stmf_sbd@0:admin"
55 #define PPPT_PATH "/devices/pseudo/pppt@0:pppt"
60 #define LU_ASCII_GUID_SIZE 32
61 #define LU_GUID_SIZE 16
62 #define OUI_ASCII_SIZE 6
63 #define HOST_ID_ASCII_SIZE 8
65 #define HOST_ID_SIZE 4
66 #define IDENT_LENGTH_BYTE 3
68 /* various initial allocation values */
70 #define ALLOC_TARGET_PORT 2048
71 #define ALLOC_PROVIDER 64
72 #define ALLOC_GROUP 2048
73 #define ALLOC_SESSION 2048
75 #define ALLOC_PP_DATA_SIZE 128*1024
76 #define ALLOC_GRP_MEMBER 256
78 #define MAX_ISCSI_NAME 223
79 #define MAX_SERIAL_SIZE 252 + 1
80 #define MAX_LU_ALIAS_SIZE 256
81 #define MAX_SBD_PROPS MAXPATHLEN + MAX_SERIAL_SIZE + MAX_LU_ALIAS_SIZE
84 #define OPEN_EXCL_STMF O_EXCL
87 #define OPEN_EXCL_SBD O_EXCL
90 #define OPEN_EXCL_PPPT O_EXCL
92 #define LOGICAL_UNIT_TYPE 0
94 #define STMF_SERVICE_TYPE 2
97 #define TARGET_GROUP 2
99 /* set default persistence here */
100 #define STMF_DEFAULT_PERSIST STMF_PERSIST_SMF
102 #define MAX_PROVIDER_RETRY 30
104 static int openStmf(int, int *fd
);
105 static int openSbd(int, int *fd
);
106 static int openPppt(int, int *fd
);
107 static int groupIoctl(int fd
, int cmd
, stmfGroupName
*);
108 static int loadStore(int fd
);
109 static int initializeConfig();
110 static int groupMemberIoctl(int fd
, int cmd
, stmfGroupName
*, stmfDevid
*);
111 static int guidCompare(const void *, const void *);
112 static int addViewEntryIoctl(int fd
, stmfGuid
*, stmfViewEntry
*);
113 static int loadHostGroups(int fd
, stmfGroupList
*);
114 static int loadTargetGroups(int fd
, stmfGroupList
*);
115 static int getStmfState(stmf_state_desc_t
*);
116 static int setStmfState(int fd
, stmf_state_desc_t
*, int);
117 static int setProviderData(int fd
, char *, nvlist_t
*, int, uint64_t *);
118 static int createDiskResource(luResourceImpl
*);
119 static int createDiskLu(diskResource
*, stmfGuid
*);
120 static int deleteDiskLu(stmfGuid
*luGuid
);
121 static int getDiskProp(luResourceImpl
*, uint32_t, char *, size_t *);
122 static int getDiskAllProps(stmfGuid
*luGuid
, luResource
*hdl
);
123 static int loadDiskPropsFromDriver(luResourceImpl
*, sbd_lu_props_t
*);
124 static int removeGuidFromDiskStore(stmfGuid
*);
125 static int addGuidToDiskStore(stmfGuid
*, char *);
126 static int persistDiskGuid(stmfGuid
*, char *, boolean_t
);
127 static int setDiskProp(luResourceImpl
*, uint32_t, const char *);
128 static int getDiskGlobalProp(uint32_t prop
, char *propVal
, size_t *propLen
);
129 static int checkHexUpper(char *);
130 static int strToShift(const char *);
131 static int niceStrToNum(const char *, uint64_t *);
132 static void diskError(uint32_t, int *);
133 static int importDiskLu(char *fname
, stmfGuid
*);
134 static int modifyDiskLu(diskResource
*, stmfGuid
*, const char *);
135 static int modifyDiskLuProp(stmfGuid
*, const char *, uint32_t, const char *);
136 static int validateModifyDiskProp(uint32_t);
137 static uint8_t iGetPersistMethod();
138 static int groupListIoctl(stmfGroupList
**, int);
139 static int iLoadGroupFromPs(stmfGroupList
**, int);
140 static int groupMemberListIoctl(stmfGroupName
*, stmfGroupProperties
**, int);
141 static int getProviderData(char *, nvlist_t
**, int, uint64_t *);
142 static int setDiskStandby(stmfGuid
*luGuid
);
143 static int setDiskGlobalProp(uint32_t, const char *);
144 static int viewEntryCompare(const void *, const void *);
145 static void deleteNonActiveLus();
146 static int loadStmfProp(int fd
);
148 static pthread_mutex_t persistenceTypeLock
= PTHREAD_MUTEX_INITIALIZER
;
149 static int iPersistType
= 0;
150 /* when B_TRUE, no need to access SMF anymore. Just use iPersistType */
151 static boolean_t iLibSetPersist
= B_FALSE
;
154 * Open for stmf module
156 * flag - open flag (OPEN_STMF, OPEN_EXCL_STMF)
157 * fd - pointer to integer. On success, contains the stmf file descriptor
160 openStmf(int flag
, int *fd
)
162 int ret
= STMF_STATUS_ERROR
;
164 if ((*fd
= open(STMF_PATH
, O_NDELAY
| O_RDONLY
| flag
)) != -1) {
165 ret
= STMF_STATUS_SUCCESS
;
167 if (errno
== EBUSY
) {
168 ret
= STMF_ERROR_BUSY
;
169 } else if (errno
== EACCES
) {
170 ret
= STMF_ERROR_PERM
;
172 ret
= STMF_STATUS_ERROR
;
174 syslog(LOG_DEBUG
, "openStmf:open failure:%s:errno(%d)",
182 * Open for sbd module
184 * flag - open flag (OPEN_SBD, OPEN_EXCL_SBD)
185 * fd - pointer to integer. On success, contains the stmf file descriptor
188 openSbd(int flag
, int *fd
)
190 int ret
= STMF_STATUS_ERROR
;
192 if ((*fd
= open(SBD_PATH
, O_NDELAY
| O_RDONLY
| flag
)) != -1) {
193 ret
= STMF_STATUS_SUCCESS
;
195 if (errno
== EBUSY
) {
196 ret
= STMF_ERROR_BUSY
;
197 } else if (errno
== EACCES
) {
198 ret
= STMF_ERROR_PERM
;
200 ret
= STMF_STATUS_ERROR
;
202 syslog(LOG_DEBUG
, "openSbd:open failure:%s:errno(%d)",
210 * Open for pppt module
212 * flag - open flag (OPEN_PPPT, OPEN_EXCL_PPPT)
213 * fd - pointer to integer. On success, contains the stmf file descriptor
216 openPppt(int flag
, int *fd
)
218 int ret
= STMF_STATUS_ERROR
;
220 if ((*fd
= open(PPPT_PATH
, O_RDONLY
| flag
)) != -1) {
221 ret
= STMF_STATUS_SUCCESS
;
223 if (errno
== EBUSY
) {
224 ret
= STMF_ERROR_BUSY
;
225 } else if (errno
== EACCES
) {
226 ret
= STMF_ERROR_PERM
;
228 ret
= STMF_STATUS_ERROR
;
230 syslog(LOG_DEBUG
, "openPppt:open failure:%s:errno(%d)",
240 * This routine should be called before any ioctl requiring initialization
241 * which is basically everything except stmfGetState(), setStmfState() and
251 ret
= stmfGetState(&state
);
252 if (ret
!= STMF_STATUS_SUCCESS
) {
256 /* if we've already initialized or in the process, return success */
257 if (state
.configState
== STMF_CONFIG_STATE_INIT_DONE
||
258 state
.configState
== STMF_CONFIG_STATE_INIT
) {
259 return (STMF_STATUS_SUCCESS
);
262 ret
= stmfLoadConfig();
263 if (ret
!= STMF_STATUS_SUCCESS
) {
265 "initializeConfig:stmfLoadConfig:error(%d)", ret
);
269 ret
= stmfGetState(&state
);
270 if (ret
!= STMF_STATUS_SUCCESS
) {
272 "initializeConfig:stmfGetState:error(%d)", ret
);
276 if (state
.configState
!= STMF_CONFIG_STATE_INIT_DONE
) {
277 syslog(LOG_DEBUG
, "initializeConfig:state.configState(%d)",
279 ret
= STMF_STATUS_ERROR
;
289 * Purpose: issue ioctl for create/delete on group
291 * cmd - valid STMF ioctl group cmd
292 * groupName - groupName to create or delete
295 groupIoctl(int fd
, int cmd
, stmfGroupName
*groupName
)
297 int ret
= STMF_STATUS_SUCCESS
;
299 stmf_iocdata_t stmfIoctl
;
300 stmf_group_name_t iGroupName
;
302 bzero(&iGroupName
, sizeof (iGroupName
));
304 bcopy(groupName
, &iGroupName
.name
, strlen((char *)groupName
));
306 iGroupName
.name_size
= strlen((char *)groupName
);
308 bzero(&stmfIoctl
, sizeof (stmfIoctl
));
310 * Issue ioctl to create the host group
312 stmfIoctl
.stmf_version
= STMF_VERSION_1
;
313 stmfIoctl
.stmf_ibuf_size
= sizeof (iGroupName
);
314 stmfIoctl
.stmf_ibuf
= (uint64_t)(unsigned long)&iGroupName
;
315 ioctlRet
= ioctl(fd
, cmd
, &stmfIoctl
);
320 ret
= STMF_ERROR_PERM
;
323 switch (stmfIoctl
.stmf_error
) {
324 case STMF_IOCERR_TG_EXISTS
:
325 case STMF_IOCERR_HG_EXISTS
:
326 ret
= STMF_ERROR_EXISTS
;
328 case STMF_IOCERR_TG_IN_USE
:
329 case STMF_IOCERR_HG_IN_USE
:
330 ret
= STMF_ERROR_GROUP_IN_USE
;
332 case STMF_IOCERR_INVALID_HG
:
333 case STMF_IOCERR_INVALID_TG
:
334 ret
= STMF_ERROR_NOT_FOUND
;
338 "groupIoctl:error(%d)",
339 stmfIoctl
.stmf_error
);
340 ret
= STMF_STATUS_ERROR
;
353 * Purpose: issue ioctl for add/remove member on group
355 * cmd - valid STMF ioctl group member cmd
356 * groupName - groupName to add to or remove from
357 * devid - group member to add or remove
360 groupMemberIoctl(int fd
, int cmd
, stmfGroupName
*groupName
, stmfDevid
*devid
)
362 int ret
= STMF_STATUS_SUCCESS
;
364 stmf_iocdata_t stmfIoctl
;
365 stmf_group_op_data_t stmfGroupData
;
367 bzero(&stmfGroupData
, sizeof (stmfGroupData
));
369 bcopy(groupName
, &stmfGroupData
.group
.name
, strlen((char *)groupName
));
371 stmfGroupData
.group
.name_size
= strlen((char *)groupName
);
372 stmfGroupData
.ident
[IDENT_LENGTH_BYTE
] = devid
->identLength
;
373 bcopy(&(devid
->ident
), &stmfGroupData
.ident
[IDENT_LENGTH_BYTE
+ 1],
376 bzero(&stmfIoctl
, sizeof (stmfIoctl
));
378 * Issue ioctl to add to the host group
380 stmfIoctl
.stmf_version
= STMF_VERSION_1
;
381 stmfIoctl
.stmf_ibuf_size
= sizeof (stmfGroupData
);
382 stmfIoctl
.stmf_ibuf
= (uint64_t)(unsigned long)&stmfGroupData
;
383 ioctlRet
= ioctl(fd
, cmd
, &stmfIoctl
);
387 switch (stmfIoctl
.stmf_error
) {
388 case STMF_IOCERR_TG_NEED_TG_OFFLINE
:
389 ret
= STMF_ERROR_TG_ONLINE
;
392 ret
= STMF_ERROR_BUSY
;
398 ret
= STMF_ERROR_PERM
;
401 switch (stmfIoctl
.stmf_error
) {
402 case STMF_IOCERR_TG_ENTRY_EXISTS
:
403 case STMF_IOCERR_HG_ENTRY_EXISTS
:
404 ret
= STMF_ERROR_EXISTS
;
406 case STMF_IOCERR_INVALID_TG_ENTRY
:
407 case STMF_IOCERR_INVALID_HG_ENTRY
:
409 STMF_ERROR_MEMBER_NOT_FOUND
;
411 case STMF_IOCERR_INVALID_TG
:
412 case STMF_IOCERR_INVALID_HG
:
414 STMF_ERROR_GROUP_NOT_FOUND
;
418 "groupMemberIoctl:error"
420 stmfIoctl
.stmf_error
);
421 ret
= STMF_STATUS_ERROR
;
436 viewEntryCompare(const void *p1
, const void *p2
)
439 stmfViewEntry
*v1
= (stmfViewEntry
*)p1
, *v2
= (stmfViewEntry
*)p2
;
440 if (v1
->veIndex
> v2
->veIndex
)
442 if (v1
->veIndex
< v2
->veIndex
)
454 guidCompare(const void *p1
, const void *p2
)
457 stmfGuid
*g1
= (stmfGuid
*)p1
, *g2
= (stmfGuid
*)p2
;
460 for (i
= 0; i
< sizeof (stmfGuid
); i
++) {
461 if (g1
->guid
[i
] > g2
->guid
[i
])
463 if (g1
->guid
[i
] < g2
->guid
[i
])
473 * Purpose: Adds an initiator to an existing host group
475 * hostGroupName - name of an existing host group
476 * hostName - name of initiator to add
479 stmfAddToHostGroup(stmfGroupName
*hostGroupName
, stmfDevid
*hostName
)
484 if (hostGroupName
== NULL
||
485 (strnlen((char *)hostGroupName
, sizeof (stmfGroupName
))
486 == sizeof (stmfGroupName
)) || hostName
== NULL
) {
487 return (STMF_ERROR_INVALID_ARG
);
491 ret
= initializeConfig();
492 if (ret
!= STMF_STATUS_SUCCESS
) {
497 * Open control node for stmf
499 if ((ret
= openStmf(OPEN_STMF
, &fd
)) != STMF_STATUS_SUCCESS
)
502 if ((ret
= groupMemberIoctl(fd
, STMF_IOCTL_ADD_HG_ENTRY
, hostGroupName
,
503 hostName
)) != STMF_STATUS_SUCCESS
) {
507 if (iGetPersistMethod() == STMF_PERSIST_NONE
) {
511 ret
= psAddHostGroupMember((char *)hostGroupName
,
512 (char *)hostName
->ident
);
514 case STMF_PS_SUCCESS
:
515 ret
= STMF_STATUS_SUCCESS
;
517 case STMF_PS_ERROR_EXISTS
:
518 ret
= STMF_ERROR_EXISTS
;
520 case STMF_PS_ERROR_GROUP_NOT_FOUND
:
521 ret
= STMF_ERROR_GROUP_NOT_FOUND
;
523 case STMF_PS_ERROR_BUSY
:
524 ret
= STMF_ERROR_BUSY
;
526 case STMF_PS_ERROR_SERVICE_NOT_FOUND
:
527 ret
= STMF_ERROR_SERVICE_NOT_FOUND
;
529 case STMF_PS_ERROR_VERSION_MISMATCH
:
530 ret
= STMF_ERROR_SERVICE_DATA_VERSION
;
534 "stmfAddToHostGroup:psAddHostGroupMember:error(%d)",
536 ret
= STMF_STATUS_ERROR
;
546 * stmfAddToTargetGroup
548 * Purpose: Adds a local port to an existing target group
550 * targetGroupName - name of an existing target group
551 * targetName - name of target to add
554 stmfAddToTargetGroup(stmfGroupName
*targetGroupName
, stmfDevid
*targetName
)
559 if (targetGroupName
== NULL
||
560 (strnlen((char *)targetGroupName
, sizeof (stmfGroupName
))
561 == sizeof (stmfGroupName
)) || targetName
== NULL
) {
562 return (STMF_ERROR_INVALID_ARG
);
566 ret
= initializeConfig();
567 if (ret
!= STMF_STATUS_SUCCESS
) {
572 * Open control node for stmf
574 if ((ret
= openStmf(OPEN_STMF
, &fd
)) != STMF_STATUS_SUCCESS
)
577 if ((ret
= groupMemberIoctl(fd
, STMF_IOCTL_ADD_TG_ENTRY
,
578 targetGroupName
, targetName
)) != STMF_STATUS_SUCCESS
) {
582 if (iGetPersistMethod() == STMF_PERSIST_NONE
) {
586 ret
= psAddTargetGroupMember((char *)targetGroupName
,
587 (char *)targetName
->ident
);
589 case STMF_PS_SUCCESS
:
590 ret
= STMF_STATUS_SUCCESS
;
592 case STMF_PS_ERROR_EXISTS
:
593 ret
= STMF_ERROR_EXISTS
;
595 case STMF_PS_ERROR_GROUP_NOT_FOUND
:
596 ret
= STMF_ERROR_GROUP_NOT_FOUND
;
598 case STMF_PS_ERROR_BUSY
:
599 ret
= STMF_ERROR_BUSY
;
601 case STMF_PS_ERROR_SERVICE_NOT_FOUND
:
602 ret
= STMF_ERROR_SERVICE_NOT_FOUND
;
604 case STMF_PS_ERROR_VERSION_MISMATCH
:
605 ret
= STMF_ERROR_SERVICE_DATA_VERSION
;
609 "stmfAddToTargetGroup:psAddTargetGroupMember:"
611 ret
= STMF_STATUS_ERROR
;
623 * Purpose: Issues ioctl to add a view entry
625 * lu - Logical Unit identifier to which the view entry is added
626 * viewEntry - view entry to add
627 * init - When set to B_TRUE, we are in the init state, i.e. don't call open
630 addViewEntryIoctl(int fd
, stmfGuid
*lu
, stmfViewEntry
*viewEntry
)
632 int ret
= STMF_STATUS_SUCCESS
;
634 stmf_iocdata_t stmfIoctl
;
635 stmf_view_op_entry_t ioctlViewEntry
;
637 bzero(&ioctlViewEntry
, sizeof (ioctlViewEntry
));
639 * don't set ve_ndx or ve_ndx_valid as ve_ndx_valid should be
642 ioctlViewEntry
.ve_lu_number_valid
= viewEntry
->luNbrValid
;
643 ioctlViewEntry
.ve_all_hosts
= viewEntry
->allHosts
;
644 ioctlViewEntry
.ve_all_targets
= viewEntry
->allTargets
;
646 if (viewEntry
->allHosts
== B_FALSE
) {
647 bcopy(viewEntry
->hostGroup
, &ioctlViewEntry
.ve_host_group
.name
,
648 sizeof (stmfGroupName
));
649 ioctlViewEntry
.ve_host_group
.name_size
=
650 strlen((char *)viewEntry
->hostGroup
);
652 if (viewEntry
->allTargets
== B_FALSE
) {
653 bcopy(viewEntry
->targetGroup
,
654 &ioctlViewEntry
.ve_target_group
.name
,
655 sizeof (stmfGroupName
));
656 ioctlViewEntry
.ve_target_group
.name_size
=
657 strlen((char *)viewEntry
->targetGroup
);
659 if (viewEntry
->luNbrValid
) {
660 bcopy(viewEntry
->luNbr
, &ioctlViewEntry
.ve_lu_nbr
,
661 sizeof (ioctlViewEntry
.ve_lu_nbr
));
663 bcopy(lu
, &ioctlViewEntry
.ve_guid
, sizeof (stmfGuid
));
665 bzero(&stmfIoctl
, sizeof (stmfIoctl
));
667 * Issue ioctl to add to the view entry
669 stmfIoctl
.stmf_version
= STMF_VERSION_1
;
670 stmfIoctl
.stmf_ibuf_size
= sizeof (ioctlViewEntry
);
671 stmfIoctl
.stmf_ibuf
= (uint64_t)(unsigned long)&ioctlViewEntry
;
672 stmfIoctl
.stmf_obuf_size
= sizeof (ioctlViewEntry
);
673 stmfIoctl
.stmf_obuf
= (uint64_t)(unsigned long)&ioctlViewEntry
;
674 ioctlRet
= ioctl(fd
, STMF_IOCTL_ADD_VIEW_ENTRY
, &stmfIoctl
);
678 ret
= STMF_ERROR_BUSY
;
681 ret
= STMF_ERROR_PERM
;
684 switch (stmfIoctl
.stmf_error
) {
685 case STMF_IOCERR_UPDATE_NEED_CFG_INIT
:
686 ret
= STMF_ERROR_CONFIG_NONE
;
689 ret
= STMF_ERROR_PERM
;
694 switch (stmfIoctl
.stmf_error
) {
695 case STMF_IOCERR_LU_NUMBER_IN_USE
:
696 ret
= STMF_ERROR_LUN_IN_USE
;
698 case STMF_IOCERR_VIEW_ENTRY_CONFLICT
:
699 ret
= STMF_ERROR_VE_CONFLICT
;
701 case STMF_IOCERR_UPDATE_NEED_CFG_INIT
:
702 ret
= STMF_ERROR_CONFIG_NONE
;
704 case STMF_IOCERR_INVALID_HG
:
705 ret
= STMF_ERROR_INVALID_HG
;
707 case STMF_IOCERR_INVALID_TG
:
708 ret
= STMF_ERROR_INVALID_TG
;
714 stmfIoctl
.stmf_error
);
715 ret
= STMF_STATUS_ERROR
;
723 /* copy lu nbr back to caller's view entry on success */
724 viewEntry
->veIndex
= ioctlViewEntry
.ve_ndx
;
725 if (ioctlViewEntry
.ve_lu_number_valid
) {
726 bcopy(&ioctlViewEntry
.ve_lu_nbr
, viewEntry
->luNbr
,
727 sizeof (ioctlViewEntry
.ve_lu_nbr
));
729 viewEntry
->luNbrValid
= B_TRUE
;
738 * Purpose: Adds a view entry to a logical unit
740 * lu - guid of the logical unit to which the view entry is added
741 * viewEntry - view entry structure to add
744 stmfAddViewEntry(stmfGuid
*lu
, stmfViewEntry
*viewEntry
)
748 stmfViewEntry iViewEntry
;
750 if (lu
== NULL
|| viewEntry
== NULL
) {
751 return (STMF_ERROR_INVALID_ARG
);
754 /* initialize and set internal view entry */
755 bzero(&iViewEntry
, sizeof (iViewEntry
));
757 if (!viewEntry
->allHosts
) {
758 bcopy(viewEntry
->hostGroup
, iViewEntry
.hostGroup
,
759 sizeof (iViewEntry
.hostGroup
));
761 iViewEntry
.allHosts
= B_TRUE
;
764 if (!viewEntry
->allTargets
) {
765 bcopy(viewEntry
->targetGroup
, iViewEntry
.targetGroup
,
766 sizeof (iViewEntry
.targetGroup
));
768 iViewEntry
.allTargets
= B_TRUE
;
771 if (viewEntry
->luNbrValid
) {
772 iViewEntry
.luNbrValid
= B_TRUE
;
773 bcopy(viewEntry
->luNbr
, iViewEntry
.luNbr
,
774 sizeof (iViewEntry
.luNbr
));
778 * set users return view entry index valid flag to false
781 viewEntry
->veIndexValid
= B_FALSE
;
783 /* Check to ensure service exists */
784 if (psCheckService() != STMF_STATUS_SUCCESS
) {
785 return (STMF_ERROR_SERVICE_NOT_FOUND
);
789 ret
= initializeConfig();
790 if (ret
!= STMF_STATUS_SUCCESS
) {
795 * Open control node for stmf
797 if ((ret
= openStmf(OPEN_STMF
, &fd
)) != STMF_STATUS_SUCCESS
)
801 * First add the view entry to the driver
803 ret
= addViewEntryIoctl(fd
, lu
, &iViewEntry
);
804 if (ret
!= STMF_STATUS_SUCCESS
) {
808 if (iGetPersistMethod() == STMF_PERSIST_NONE
) {
813 * If the add to driver was successful, add it to the persistent
816 ret
= psAddViewEntry(lu
, &iViewEntry
);
818 case STMF_PS_SUCCESS
:
819 ret
= STMF_STATUS_SUCCESS
;
821 case STMF_PS_ERROR_NOT_FOUND
:
822 ret
= STMF_ERROR_NOT_FOUND
;
824 case STMF_PS_ERROR_BUSY
:
825 ret
= STMF_ERROR_BUSY
;
827 case STMF_PS_ERROR_SERVICE_NOT_FOUND
:
828 ret
= STMF_ERROR_SERVICE_NOT_FOUND
;
830 case STMF_PS_ERROR_VERSION_MISMATCH
:
831 ret
= STMF_ERROR_SERVICE_DATA_VERSION
;
835 "stmfAddViewEntry:psAddViewEntry:error(%d)", ret
);
836 ret
= STMF_STATUS_ERROR
;
843 if (ret
== STMF_STATUS_SUCCESS
) {
844 /* set caller's view entry on success */
845 viewEntry
->veIndexValid
= iViewEntry
.veIndexValid
;
846 viewEntry
->veIndex
= iViewEntry
.veIndex
;
847 viewEntry
->luNbrValid
= B_TRUE
;
848 bcopy(iViewEntry
.luNbr
, viewEntry
->luNbr
,
849 sizeof (iViewEntry
.luNbr
));
855 * stmfClearProviderData
857 * Purpose: delete all provider data for specified provider
859 * providerName - name of provider for which data should be deleted
862 stmfClearProviderData(char *providerName
, int providerType
)
868 stmf_iocdata_t stmfIoctl
;
869 stmf_ppioctl_data_t ppi
;
872 ret
= initializeConfig();
873 if (ret
!= STMF_STATUS_SUCCESS
) {
877 if (providerName
== NULL
) {
878 return (STMF_ERROR_INVALID_ARG
);
881 if (providerType
!= STMF_LU_PROVIDER_TYPE
&&
882 providerType
!= STMF_PORT_PROVIDER_TYPE
) {
883 return (STMF_ERROR_INVALID_ARG
);
887 * Open control node for stmf
889 if ((ret
= openStmf(OPEN_STMF
, &fd
)) != STMF_STATUS_SUCCESS
)
892 bzero(&ppi
, sizeof (ppi
));
894 (void) strncpy(ppi
.ppi_name
, providerName
, sizeof (ppi
.ppi_name
));
896 switch (providerType
) {
897 case STMF_LU_PROVIDER_TYPE
:
898 ppi
.ppi_lu_provider
= 1;
900 case STMF_PORT_PROVIDER_TYPE
:
901 ppi
.ppi_port_provider
= 1;
904 ret
= STMF_ERROR_INVALID_ARG
;
908 bzero(&stmfIoctl
, sizeof (stmfIoctl
));
910 stmfIoctl
.stmf_version
= STMF_VERSION_1
;
911 stmfIoctl
.stmf_ibuf_size
= sizeof (stmf_ppioctl_data_t
);
912 stmfIoctl
.stmf_ibuf
= (uint64_t)(unsigned long)&ppi
;
914 ioctlRet
= ioctl(fd
, STMF_IOCTL_CLEAR_PP_DATA
, &stmfIoctl
);
917 switch (savedErrno
) {
919 ret
= STMF_ERROR_BUSY
;
923 ret
= STMF_ERROR_PERM
;
927 "stmfClearProviderData:ioctl error(%d)",
929 ret
= STMF_STATUS_ERROR
;
932 if (savedErrno
!= ENOENT
) {
937 if (iGetPersistMethod() == STMF_PERSIST_NONE
) {
941 ret
= psClearProviderData(providerName
, providerType
);
943 case STMF_PS_SUCCESS
:
944 ret
= STMF_STATUS_SUCCESS
;
946 case STMF_PS_ERROR_NOT_FOUND
:
947 ret
= STMF_ERROR_NOT_FOUND
;
949 case STMF_PS_ERROR_BUSY
:
950 ret
= STMF_ERROR_BUSY
;
952 case STMF_PS_ERROR_SERVICE_NOT_FOUND
:
953 ret
= STMF_ERROR_SERVICE_NOT_FOUND
;
955 case STMF_PS_ERROR_VERSION_MISMATCH
:
956 ret
= STMF_ERROR_SERVICE_DATA_VERSION
;
960 "stmfClearProviderData:psClearProviderData"
962 ret
= STMF_STATUS_ERROR
;
972 * stmfCreateHostGroup
974 * Purpose: Create a new initiator group
976 * hostGroupName - name of host group to create
979 stmfCreateHostGroup(stmfGroupName
*hostGroupName
)
984 if (hostGroupName
== NULL
||
985 (strnlen((char *)hostGroupName
, sizeof (stmfGroupName
))
986 == sizeof (stmfGroupName
))) {
987 return (STMF_ERROR_INVALID_ARG
);
990 /* Check to ensure service exists */
991 if (psCheckService() != STMF_STATUS_SUCCESS
) {
992 return (STMF_ERROR_SERVICE_NOT_FOUND
);
996 ret
= initializeConfig();
997 if (ret
!= STMF_STATUS_SUCCESS
) {
1002 * Open control node for stmf
1004 if ((ret
= openStmf(OPEN_STMF
, &fd
)) != STMF_STATUS_SUCCESS
)
1007 if ((ret
= groupIoctl(fd
, STMF_IOCTL_CREATE_HOST_GROUP
,
1008 hostGroupName
)) != STMF_STATUS_SUCCESS
) {
1012 if (iGetPersistMethod() == STMF_PERSIST_NONE
) {
1016 ret
= psCreateHostGroup((char *)hostGroupName
);
1018 case STMF_PS_SUCCESS
:
1019 ret
= STMF_STATUS_SUCCESS
;
1021 case STMF_PS_ERROR_EXISTS
:
1022 ret
= STMF_ERROR_EXISTS
;
1024 case STMF_PS_ERROR_BUSY
:
1025 ret
= STMF_ERROR_BUSY
;
1027 case STMF_PS_ERROR_SERVICE_NOT_FOUND
:
1028 ret
= STMF_ERROR_SERVICE_NOT_FOUND
;
1030 case STMF_PS_ERROR_VERSION_MISMATCH
:
1031 ret
= STMF_ERROR_SERVICE_DATA_VERSION
;
1035 "stmfCreateHostGroup:psCreateHostGroup:error(%d)",
1037 ret
= STMF_STATUS_ERROR
;
1049 * Purpose: Create a logical unit
1051 * hdl - handle to logical unit resource created via stmfCreateLuResource
1053 * luGuid - If non-NULL, on success, contains the guid of the created logical
1057 stmfCreateLu(luResource hdl
, stmfGuid
*luGuid
)
1059 int ret
= STMF_STATUS_SUCCESS
;
1060 luResourceImpl
*luPropsHdl
= hdl
;
1063 return (STMF_ERROR_INVALID_ARG
);
1066 if (luPropsHdl
->type
== STMF_DISK
) {
1067 ret
= createDiskLu((diskResource
*)luPropsHdl
->resource
,
1070 return (STMF_ERROR_INVALID_ARG
);
1077 * stmfCreateLuResource
1079 * Purpose: Create resource handle for a logical unit
1081 * dType - Type of logical unit resource to create
1084 * hdl - pointer to luResource
1087 stmfCreateLuResource(uint16_t dType
, luResource
*hdl
)
1089 int ret
= STMF_STATUS_SUCCESS
;
1091 if (dType
!= STMF_DISK
|| hdl
== NULL
) {
1092 return (STMF_ERROR_INVALID_ARG
);
1095 *hdl
= calloc(1, sizeof (luResourceImpl
));
1097 return (STMF_ERROR_NOMEM
);
1100 ret
= createDiskResource((luResourceImpl
*)*hdl
);
1101 if (ret
!= STMF_STATUS_SUCCESS
) {
1106 return (STMF_STATUS_SUCCESS
);
1110 * Creates a disk logical unit
1112 * disk - pointer to diskResource structure that represents the properties
1113 * for the disk logical unit to be created.
1116 createDiskLu(diskResource
*disk
, stmfGuid
*createdGuid
)
1118 int ret
= STMF_STATUS_SUCCESS
;
1119 int dataFileNameLen
= 0;
1120 int metaFileNameLen
= 0;
1121 int serialNumLen
= 0;
1123 int luMgmtUrlLen
= 0;
1130 stmf_iocdata_t sbdIoctl
= {0};
1132 sbd_create_and_reg_lu_t
*sbdLu
= NULL
;
1135 * Open control node for sbd
1137 if ((ret
= openSbd(OPEN_SBD
, &fd
)) != STMF_STATUS_SUCCESS
)
1140 /* data file name must be specified */
1141 if (disk
->luDataFileNameValid
) {
1142 dataFileNameLen
= strlen(disk
->luDataFileName
);
1145 return (STMF_ERROR_MISSING_PROP_VAL
);
1148 sluBufSize
+= dataFileNameLen
+ 1;
1150 if (disk
->luMetaFileNameValid
) {
1151 metaFileNameLen
= strlen(disk
->luMetaFileName
);
1152 sluBufSize
+= metaFileNameLen
+ 1;
1155 serialNumLen
= strlen(disk
->serialNum
);
1156 sluBufSize
+= serialNumLen
;
1158 if (disk
->luAliasValid
) {
1159 luAliasLen
= strlen(disk
->luAlias
);
1160 sluBufSize
+= luAliasLen
+ 1;
1163 if (disk
->luMgmtUrlValid
) {
1164 luMgmtUrlLen
= strlen(disk
->luMgmtUrl
);
1165 sluBufSize
+= luMgmtUrlLen
+ 1;
1169 * 8 is the size of the buffer set aside for
1170 * concatenation of variable length fields
1172 sbdLu
= (sbd_create_and_reg_lu_t
*)calloc(1,
1173 sizeof (sbd_create_and_reg_lu_t
) + sluBufSize
- 8);
1174 if (sbdLu
== NULL
) {
1175 return (STMF_ERROR_NOMEM
);
1178 sbdLu
->slu_struct_size
= sizeof (sbd_create_and_reg_lu_t
) +
1181 if (metaFileNameLen
) {
1182 sbdLu
->slu_meta_fname_valid
= 1;
1183 sbdLu
->slu_meta_fname_off
= bufOffset
;
1184 bcopy(disk
->luMetaFileName
, &(sbdLu
->slu_buf
[bufOffset
]),
1185 metaFileNameLen
+ 1);
1186 bufOffset
+= metaFileNameLen
+ 1;
1189 bcopy(disk
->luDataFileName
, &(sbdLu
->slu_buf
[bufOffset
]),
1190 dataFileNameLen
+ 1);
1191 sbdLu
->slu_data_fname_off
= bufOffset
;
1192 bufOffset
+= dataFileNameLen
+ 1;
1194 /* currently, serial # is not passed null terminated to the driver */
1195 if (disk
->serialNumValid
) {
1196 sbdLu
->slu_serial_valid
= 1;
1197 sbdLu
->slu_serial_off
= bufOffset
;
1198 sbdLu
->slu_serial_size
= serialNumLen
;
1199 bcopy(disk
->serialNum
, &(sbdLu
->slu_buf
[bufOffset
]),
1201 bufOffset
+= serialNumLen
;
1204 if (disk
->luAliasValid
) {
1205 sbdLu
->slu_alias_valid
= 1;
1206 sbdLu
->slu_alias_off
= bufOffset
;
1207 bcopy(disk
->luAlias
, &(sbdLu
->slu_buf
[bufOffset
]),
1209 bufOffset
+= luAliasLen
+ 1;
1212 if (disk
->luMgmtUrlValid
) {
1213 sbdLu
->slu_mgmt_url_valid
= 1;
1214 sbdLu
->slu_mgmt_url_off
= bufOffset
;
1215 bcopy(disk
->luMgmtUrl
, &(sbdLu
->slu_buf
[bufOffset
]),
1217 bufOffset
+= luMgmtUrlLen
+ 1;
1220 if (disk
->luSizeValid
) {
1221 sbdLu
->slu_lu_size_valid
= 1;
1222 sbdLu
->slu_lu_size
= disk
->luSize
;
1225 if (disk
->luGuidValid
) {
1226 sbdLu
->slu_guid_valid
= 1;
1227 bcopy(disk
->luGuid
, sbdLu
->slu_guid
, sizeof (disk
->luGuid
));
1230 if (disk
->vidValid
) {
1231 sbdLu
->slu_vid_valid
= 1;
1232 bcopy(disk
->vid
, sbdLu
->slu_vid
, sizeof (disk
->vid
));
1235 if (disk
->pidValid
) {
1236 sbdLu
->slu_pid_valid
= 1;
1237 bcopy(disk
->pid
, sbdLu
->slu_pid
, sizeof (disk
->pid
));
1240 if (disk
->revValid
) {
1241 sbdLu
->slu_rev_valid
= 1;
1242 bcopy(disk
->rev
, sbdLu
->slu_rev
, sizeof (disk
->rev
));
1245 if (disk
->companyIdValid
) {
1246 sbdLu
->slu_company_id_valid
= 1;
1247 sbdLu
->slu_company_id
= disk
->companyId
;
1250 if (disk
->hostIdValid
) {
1251 sbdLu
->slu_host_id_valid
= 1;
1252 sbdLu
->slu_host_id
= disk
->hostId
;
1255 if (disk
->blkSizeValid
) {
1256 sbdLu
->slu_blksize_valid
= 1;
1257 sbdLu
->slu_blksize
= disk
->blkSize
;
1260 if (disk
->writeProtectEnableValid
) {
1261 if (disk
->writeProtectEnable
) {
1262 sbdLu
->slu_write_protected
= 1;
1266 if (disk
->writebackCacheDisableValid
) {
1267 sbdLu
->slu_writeback_cache_disable_valid
= 1;
1268 if (disk
->writebackCacheDisable
) {
1269 sbdLu
->slu_writeback_cache_disable
= 1;
1273 sbdIoctl
.stmf_version
= STMF_VERSION_1
;
1274 sbdIoctl
.stmf_ibuf_size
= sbdLu
->slu_struct_size
;
1275 sbdIoctl
.stmf_ibuf
= (uint64_t)(unsigned long)sbdLu
;
1276 sbdIoctl
.stmf_obuf_size
= sbdLu
->slu_struct_size
;
1277 sbdIoctl
.stmf_obuf
= (uint64_t)(unsigned long)sbdLu
;
1279 ioctlRet
= ioctl(fd
, SBD_IOCTL_CREATE_AND_REGISTER_LU
, &sbdIoctl
);
1280 if (ioctlRet
!= 0) {
1282 switch (savedErrno
) {
1284 ret
= STMF_ERROR_BUSY
;
1288 ret
= STMF_ERROR_PERM
;
1291 diskError(sbdIoctl
.stmf_error
, &ret
);
1292 if (ret
== STMF_STATUS_ERROR
) {
1294 "createDiskLu:ioctl "
1295 "error(%d) (%d) (%d)", ioctlRet
,
1296 sbdIoctl
.stmf_error
, savedErrno
);
1302 if (ret
!= STMF_STATUS_SUCCESS
) {
1307 * on success, copy the resulting guid into the caller's guid if not
1311 bcopy(sbdLu
->slu_guid
, createdGuid
->guid
,
1312 sizeof (sbdLu
->slu_guid
));
1315 bcopy(sbdLu
->slu_guid
, guid
.guid
, sizeof (sbdLu
->slu_guid
));
1316 if (disk
->luMetaFileNameValid
) {
1317 ret
= addGuidToDiskStore(&guid
, disk
->luMetaFileName
);
1319 ret
= addGuidToDiskStore(&guid
, disk
->luDataFileName
);
1331 * Purpose: Import a previously created logical unit
1333 * dType - Type of logical unit
1336 * luGuid - If non-NULL, on success, contains the guid of the imported logical
1339 * fname - A file name where the metadata resides
1343 stmfImportLu(uint16_t dType
, char *fname
, stmfGuid
*luGuid
)
1345 int ret
= STMF_STATUS_SUCCESS
;
1347 if (dType
== STMF_DISK
) {
1348 ret
= importDiskLu(fname
, luGuid
);
1350 return (STMF_ERROR_INVALID_ARG
);
1359 * filename - filename to import
1360 * createdGuid - if not NULL, on success contains the imported guid
1364 importDiskLu(char *fname
, stmfGuid
*createdGuid
)
1366 int ret
= STMF_STATUS_SUCCESS
;
1370 int metaFileNameLen
;
1373 sbd_import_lu_t
*sbdLu
= NULL
;
1374 stmf_iocdata_t sbdIoctl
= {0};
1376 if (fname
== NULL
) {
1377 return (STMF_ERROR_INVALID_ARG
);
1381 * Open control node for sbd
1383 if ((ret
= openSbd(OPEN_SBD
, &fd
)) != STMF_STATUS_SUCCESS
)
1386 metaFileNameLen
= strlen(fname
);
1387 iluBufSize
+= metaFileNameLen
+ 1;
1390 * 8 is the size of the buffer set aside for
1391 * concatenation of variable length fields
1393 sbdLu
= (sbd_import_lu_t
*)calloc(1,
1394 sizeof (sbd_import_lu_t
) + iluBufSize
- 8);
1395 if (sbdLu
== NULL
) {
1397 return (STMF_ERROR_NOMEM
);
1401 * Accept either a data file or meta data file.
1402 * sbd will do the right thing here either way.
1403 * i.e. if it's a data file, it assumes that the
1404 * meta data is shared with the data.
1406 (void) strncpy(sbdLu
->ilu_meta_fname
, fname
, metaFileNameLen
);
1408 sbdLu
->ilu_struct_size
= sizeof (sbd_import_lu_t
) + iluBufSize
- 8;
1410 sbdIoctl
.stmf_version
= STMF_VERSION_1
;
1411 sbdIoctl
.stmf_ibuf_size
= sbdLu
->ilu_struct_size
;
1412 sbdIoctl
.stmf_ibuf
= (uint64_t)(unsigned long)sbdLu
;
1413 sbdIoctl
.stmf_obuf_size
= sbdLu
->ilu_struct_size
;
1414 sbdIoctl
.stmf_obuf
= (uint64_t)(unsigned long)sbdLu
;
1416 ioctlRet
= ioctl(fd
, SBD_IOCTL_IMPORT_LU
, &sbdIoctl
);
1417 if (ioctlRet
!= 0) {
1419 if (createdGuid
&& sbdIoctl
.stmf_error
==
1420 SBD_RET_FILE_ALREADY_REGISTERED
) {
1421 bcopy(sbdLu
->ilu_ret_guid
, createdGuid
->guid
,
1422 sizeof (sbdLu
->ilu_ret_guid
));
1426 switch (savedErrno
) {
1428 ret
= STMF_ERROR_BUSY
;
1432 ret
= STMF_ERROR_PERM
;
1435 diskError(sbdIoctl
.stmf_error
, &ret
);
1436 if (ret
== STMF_STATUS_ERROR
) {
1438 "importDiskLu:ioctl "
1439 "error(%d) (%d) (%d)", ioctlRet
,
1440 sbdIoctl
.stmf_error
, savedErrno
);
1447 if (ret
!= STMF_STATUS_SUCCESS
) {
1452 * on success, copy the resulting guid into the caller's guid if not
1453 * NULL and add it to the persistent store for sbd
1456 bcopy(sbdLu
->ilu_ret_guid
, createdGuid
->guid
,
1457 sizeof (sbdLu
->ilu_ret_guid
));
1458 ret
= addGuidToDiskStore(createdGuid
, fname
);
1460 bcopy(sbdLu
->ilu_ret_guid
, iGuid
.guid
,
1461 sizeof (sbdLu
->ilu_ret_guid
));
1462 ret
= addGuidToDiskStore(&iGuid
, fname
);
1473 * Purpose: Translate sbd driver error
1476 diskError(uint32_t stmfError
, int *ret
)
1478 switch (stmfError
) {
1479 case SBD_RET_META_CREATION_FAILED
:
1480 case SBD_RET_ZFS_META_CREATE_FAILED
:
1481 *ret
= STMF_ERROR_META_CREATION
;
1483 case SBD_RET_INVALID_BLKSIZE
:
1484 *ret
= STMF_ERROR_INVALID_BLKSIZE
;
1486 case SBD_RET_FILE_ALREADY_REGISTERED
:
1487 *ret
= STMF_ERROR_FILE_IN_USE
;
1489 case SBD_RET_GUID_ALREADY_REGISTERED
:
1490 *ret
= STMF_ERROR_GUID_IN_USE
;
1492 case SBD_RET_META_PATH_NOT_ABSOLUTE
:
1493 case SBD_RET_META_FILE_LOOKUP_FAILED
:
1494 case SBD_RET_META_FILE_OPEN_FAILED
:
1495 case SBD_RET_META_FILE_GETATTR_FAILED
:
1496 case SBD_RET_NO_META
:
1497 *ret
= STMF_ERROR_META_FILE_NAME
;
1499 case SBD_RET_DATA_PATH_NOT_ABSOLUTE
:
1500 case SBD_RET_DATA_FILE_LOOKUP_FAILED
:
1501 case SBD_RET_DATA_FILE_OPEN_FAILED
:
1502 case SBD_RET_DATA_FILE_GETATTR_FAILED
:
1503 *ret
= STMF_ERROR_DATA_FILE_NAME
;
1505 case SBD_RET_FILE_SIZE_ERROR
:
1506 *ret
= STMF_ERROR_FILE_SIZE_INVALID
;
1508 case SBD_RET_SIZE_OUT_OF_RANGE
:
1509 *ret
= STMF_ERROR_SIZE_OUT_OF_RANGE
;
1511 case SBD_RET_LU_BUSY
:
1512 *ret
= STMF_ERROR_LU_BUSY
;
1514 case SBD_RET_WRITE_CACHE_SET_FAILED
:
1515 *ret
= STMF_ERROR_WRITE_CACHE_SET
;
1517 case SBD_RET_ACCESS_STATE_FAILED
:
1518 *ret
= STMF_ERROR_ACCESS_STATE_SET
;
1521 *ret
= STMF_STATUS_ERROR
;
1527 * Creates a logical unit resource of type STMF_DISK.
1529 * No defaults should be set here as all defaults are derived from the
1530 * driver's default settings.
1533 createDiskResource(luResourceImpl
*hdl
)
1535 hdl
->type
= STMF_DISK
;
1537 hdl
->resource
= calloc(1, sizeof (diskResource
));
1538 if (hdl
->resource
== NULL
) {
1539 return (STMF_ERROR_NOMEM
);
1542 return (STMF_STATUS_SUCCESS
);
1548 * Purpose: Delete a logical unit
1550 * hdl - handle to logical unit resource created via stmfCreateLuResource
1552 * luGuid - If non-NULL, on success, contains the guid of the created logical
1556 stmfDeleteLu(stmfGuid
*luGuid
)
1558 int ret
= STMF_STATUS_SUCCESS
;
1559 stmfLogicalUnitProperties luProps
;
1561 if (luGuid
== NULL
) {
1562 return (STMF_ERROR_INVALID_ARG
);
1565 /* Check logical unit provider name to call correct dtype function */
1566 if ((ret
= stmfGetLogicalUnitProperties(luGuid
, &luProps
))
1567 != STMF_STATUS_SUCCESS
) {
1570 if (strcmp(luProps
.providerName
, "sbd") == 0) {
1571 ret
= deleteDiskLu(luGuid
);
1572 } else if (luProps
.status
== STMF_LOGICAL_UNIT_UNREGISTERED
) {
1573 return (STMF_ERROR_NOT_FOUND
);
1575 return (STMF_ERROR_INVALID_ARG
);
1583 deleteDiskLu(stmfGuid
*luGuid
)
1585 int ret
= STMF_STATUS_SUCCESS
;
1589 sbd_delete_lu_t deleteLu
= {0};
1591 stmf_iocdata_t sbdIoctl
= {0};
1594 * Open control node for sbd
1596 if ((ret
= openSbd(OPEN_SBD
, &fd
)) != STMF_STATUS_SUCCESS
)
1599 ret
= removeGuidFromDiskStore(luGuid
);
1600 if (ret
!= STMF_STATUS_SUCCESS
) {
1604 bcopy(luGuid
, deleteLu
.dlu_guid
, sizeof (deleteLu
.dlu_guid
));
1605 deleteLu
.dlu_by_guid
= 1;
1607 sbdIoctl
.stmf_version
= STMF_VERSION_1
;
1608 sbdIoctl
.stmf_ibuf_size
= sizeof (deleteLu
);
1609 sbdIoctl
.stmf_ibuf
= (uint64_t)(unsigned long)&deleteLu
;
1610 ioctlRet
= ioctl(fd
, SBD_IOCTL_DELETE_LU
, &sbdIoctl
);
1611 if (ioctlRet
!= 0) {
1613 switch (savedErrno
) {
1615 ret
= STMF_ERROR_BUSY
;
1619 ret
= STMF_ERROR_PERM
;
1622 ret
= STMF_ERROR_NOT_FOUND
;
1626 "deleteDiskLu:ioctl error(%d) (%d) (%d)",
1627 ioctlRet
, sbdIoctl
.stmf_error
, savedErrno
);
1628 ret
= STMF_STATUS_ERROR
;
1641 * Purpose: Sets access state to standby
1643 * luGuid - guid of registered logical unit
1647 stmfLuStandby(stmfGuid
*luGuid
)
1649 int ret
= STMF_STATUS_SUCCESS
;
1650 stmfLogicalUnitProperties luProps
;
1652 if (luGuid
== NULL
) {
1653 return (STMF_ERROR_INVALID_ARG
);
1656 /* Check logical unit provider name to call correct dtype function */
1657 if ((ret
= stmfGetLogicalUnitProperties(luGuid
, &luProps
))
1658 != STMF_STATUS_SUCCESS
) {
1661 if (strcmp(luProps
.providerName
, "sbd") == 0) {
1662 ret
= setDiskStandby(luGuid
);
1663 } else if (luProps
.status
== STMF_LOGICAL_UNIT_UNREGISTERED
) {
1664 return (STMF_ERROR_NOT_FOUND
);
1666 return (STMF_ERROR_INVALID_ARG
);
1674 setDiskStandby(stmfGuid
*luGuid
)
1676 int ret
= STMF_STATUS_SUCCESS
;
1677 stmf_iocdata_t sbdIoctl
= {0};
1678 sbd_set_lu_standby_t sbdLu
= {0};
1684 * Open control node for sbd
1686 if ((ret
= openSbd(OPEN_SBD
, &fd
)) != STMF_STATUS_SUCCESS
)
1689 bcopy(luGuid
, &sbdLu
.stlu_guid
, sizeof (stmfGuid
));
1691 sbdIoctl
.stmf_version
= STMF_VERSION_1
;
1692 sbdIoctl
.stmf_ibuf_size
= sizeof (sbd_set_lu_standby_t
);
1693 sbdIoctl
.stmf_ibuf
= (uint64_t)(unsigned long)&sbdLu
;
1695 ioctlRet
= ioctl(fd
, SBD_IOCTL_SET_LU_STANDBY
, &sbdIoctl
);
1696 if (ioctlRet
!= 0) {
1698 switch (savedErrno
) {
1700 ret
= STMF_ERROR_BUSY
;
1704 ret
= STMF_ERROR_PERM
;
1707 diskError(sbdIoctl
.stmf_error
, &ret
);
1708 if (ret
== STMF_STATUS_ERROR
) {
1710 "setDiskStandby:ioctl "
1711 "error(%d) (%d) (%d)", ioctlRet
,
1712 sbdIoctl
.stmf_error
, savedErrno
);
1724 * Purpose: Modify properties of a logical unit
1726 * luGuid - guid of registered logical unit
1727 * prop - property to modify
1728 * propVal - property value to set
1732 stmfModifyLu(stmfGuid
*luGuid
, uint32_t prop
, const char *propVal
)
1734 int ret
= STMF_STATUS_SUCCESS
;
1735 stmfLogicalUnitProperties luProps
;
1737 if (luGuid
== NULL
) {
1738 return (STMF_ERROR_INVALID_ARG
);
1741 /* Check logical unit provider name to call correct dtype function */
1742 if ((ret
= stmfGetLogicalUnitProperties(luGuid
, &luProps
))
1743 != STMF_STATUS_SUCCESS
) {
1746 if (strcmp(luProps
.providerName
, "sbd") == 0) {
1747 ret
= modifyDiskLuProp(luGuid
, NULL
, prop
, propVal
);
1748 } else if (luProps
.status
== STMF_LOGICAL_UNIT_UNREGISTERED
) {
1749 return (STMF_ERROR_NOT_FOUND
);
1751 return (STMF_ERROR_INVALID_ARG
);
1759 * stmfModifyLuByFname
1761 * Purpose: Modify a device by filename. Device does not need to be registered.
1763 * dType - type of device to modify
1766 * fname - filename or meta filename
1767 * prop - valid property identifier
1768 * propVal - property value
1772 stmfModifyLuByFname(uint16_t dType
, const char *fname
, uint32_t prop
,
1773 const char *propVal
)
1775 int ret
= STMF_STATUS_SUCCESS
;
1776 if (fname
== NULL
) {
1777 return (STMF_ERROR_INVALID_ARG
);
1780 if (dType
== STMF_DISK
) {
1781 ret
= modifyDiskLuProp(NULL
, fname
, prop
, propVal
);
1783 return (STMF_ERROR_INVALID_ARG
);
1790 modifyDiskLuProp(stmfGuid
*luGuid
, const char *fname
, uint32_t prop
,
1791 const char *propVal
)
1793 int ret
= STMF_STATUS_SUCCESS
;
1794 luResource hdl
= NULL
;
1795 luResourceImpl
*luPropsHdl
;
1797 ret
= stmfCreateLuResource(STMF_DISK
, &hdl
);
1798 if (ret
!= STMF_STATUS_SUCCESS
) {
1801 ret
= validateModifyDiskProp(prop
);
1802 if (ret
!= STMF_STATUS_SUCCESS
) {
1803 (void) stmfFreeLuResource(hdl
);
1804 return (STMF_ERROR_INVALID_PROP
);
1806 ret
= stmfSetLuProp(hdl
, prop
, propVal
);
1807 if (ret
!= STMF_STATUS_SUCCESS
) {
1808 (void) stmfFreeLuResource(hdl
);
1812 ret
= modifyDiskLu((diskResource
*)luPropsHdl
->resource
, luGuid
, fname
);
1813 (void) stmfFreeLuResource(hdl
);
1818 validateModifyDiskProp(uint32_t prop
)
1821 case STMF_LU_PROP_ALIAS
:
1822 case STMF_LU_PROP_SIZE
:
1823 case STMF_LU_PROP_MGMT_URL
:
1824 case STMF_LU_PROP_WRITE_PROTECT
:
1825 case STMF_LU_PROP_WRITE_CACHE_DISABLE
:
1826 return (STMF_STATUS_SUCCESS
);
1828 return (STMF_STATUS_ERROR
);
1833 modifyDiskLu(diskResource
*disk
, stmfGuid
*luGuid
, const char *fname
)
1835 int ret
= STMF_STATUS_SUCCESS
;
1837 int luMgmtUrlLen
= 0;
1844 stmf_iocdata_t sbdIoctl
= {0};
1846 sbd_modify_lu_t
*sbdLu
= NULL
;
1848 if (luGuid
== NULL
&& fname
== NULL
) {
1849 return (STMF_ERROR_INVALID_ARG
);
1853 fnameSize
= strlen(fname
) + 1;
1854 mluBufSize
+= fnameSize
;
1858 * Open control node for sbd
1860 if ((ret
= openSbd(OPEN_SBD
, &fd
)) != STMF_STATUS_SUCCESS
)
1863 if (disk
->luAliasValid
) {
1864 luAliasLen
= strlen(disk
->luAlias
);
1865 mluBufSize
+= luAliasLen
+ 1;
1868 if (disk
->luMgmtUrlValid
) {
1869 luMgmtUrlLen
= strlen(disk
->luMgmtUrl
);
1870 mluBufSize
+= luMgmtUrlLen
+ 1;
1874 * 8 is the size of the buffer set aside for
1875 * concatenation of variable length fields
1877 sbdLu
= (sbd_modify_lu_t
*)calloc(1,
1878 sizeof (sbd_modify_lu_t
) + mluBufSize
- 8 + fnameSize
);
1879 if (sbdLu
== NULL
) {
1881 return (STMF_ERROR_NOMEM
);
1884 sbdLu
->mlu_struct_size
= sizeof (sbd_modify_lu_t
) +
1885 mluBufSize
- 8 + fnameSize
;
1887 if (disk
->luAliasValid
) {
1888 sbdLu
->mlu_alias_valid
= 1;
1889 sbdLu
->mlu_alias_off
= bufOffset
;
1890 bcopy(disk
->luAlias
, &(sbdLu
->mlu_buf
[bufOffset
]),
1892 bufOffset
+= luAliasLen
+ 1;
1895 if (disk
->luMgmtUrlValid
) {
1896 sbdLu
->mlu_mgmt_url_valid
= 1;
1897 sbdLu
->mlu_mgmt_url_off
= bufOffset
;
1898 bcopy(disk
->luMgmtUrl
, &(sbdLu
->mlu_buf
[bufOffset
]),
1900 bufOffset
+= luMgmtUrlLen
+ 1;
1903 if (disk
->luSizeValid
) {
1904 sbdLu
->mlu_lu_size_valid
= 1;
1905 sbdLu
->mlu_lu_size
= disk
->luSize
;
1908 if (disk
->writeProtectEnableValid
) {
1909 sbdLu
->mlu_write_protected_valid
= 1;
1910 if (disk
->writeProtectEnable
) {
1911 sbdLu
->mlu_write_protected
= 1;
1915 if (disk
->writebackCacheDisableValid
) {
1916 sbdLu
->mlu_writeback_cache_disable_valid
= 1;
1917 if (disk
->writebackCacheDisable
) {
1918 sbdLu
->mlu_writeback_cache_disable
= 1;
1923 bcopy(luGuid
, sbdLu
->mlu_input_guid
, sizeof (stmfGuid
));
1924 sbdLu
->mlu_by_guid
= 1;
1926 sbdLu
->mlu_fname_off
= bufOffset
;
1927 bcopy(fname
, &(sbdLu
->mlu_buf
[bufOffset
]), fnameSize
+ 1);
1928 sbdLu
->mlu_by_fname
= 1;
1931 sbdIoctl
.stmf_version
= STMF_VERSION_1
;
1932 sbdIoctl
.stmf_ibuf_size
= sbdLu
->mlu_struct_size
;
1933 sbdIoctl
.stmf_ibuf
= (uint64_t)(unsigned long)sbdLu
;
1935 ioctlRet
= ioctl(fd
, SBD_IOCTL_MODIFY_LU
, &sbdIoctl
);
1936 if (ioctlRet
!= 0) {
1938 switch (savedErrno
) {
1940 ret
= STMF_ERROR_BUSY
;
1944 ret
= STMF_ERROR_PERM
;
1947 diskError(sbdIoctl
.stmf_error
, &ret
);
1948 if (ret
== STMF_STATUS_ERROR
) {
1950 "modifyDiskLu:ioctl "
1951 "error(%d) (%d) (%d)", ioctlRet
,
1952 sbdIoctl
.stmf_error
, savedErrno
);
1958 if (ret
!= STMF_STATUS_SUCCESS
) {
1969 * removeGuidFromDiskStore
1971 * Purpose: delete a logical unit from the sbd provider data
1974 removeGuidFromDiskStore(stmfGuid
*guid
)
1976 return (persistDiskGuid(guid
, NULL
, B_FALSE
));
1981 * addGuidToDiskStore
1983 * Purpose: add a logical unit to the sbd provider data
1986 addGuidToDiskStore(stmfGuid
*guid
, char *filename
)
1988 return (persistDiskGuid(guid
, filename
, B_TRUE
));
1995 * Purpose: Persist or unpersist a guid for the sbd provider data
1999 persistDiskGuid(stmfGuid
*guid
, char *filename
, boolean_t persist
)
2001 char guidAsciiBuf
[LU_ASCII_GUID_SIZE
+ 1] = {0};
2002 nvlist_t
*nvl
= NULL
;
2005 boolean_t retryGetProviderData
= B_FALSE
;
2006 boolean_t newData
= B_FALSE
;
2007 int ret
= STMF_STATUS_SUCCESS
;
2011 /* if we're persisting a guid, there must be a filename */
2012 if (persist
&& !filename
) {
2016 /* guid is stored in lowercase ascii hex */
2017 (void) snprintf(guidAsciiBuf
, sizeof (guidAsciiBuf
),
2018 "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
2019 "%02x%02x%02x%02x%02x%02x",
2020 guid
->guid
[0], guid
->guid
[1], guid
->guid
[2], guid
->guid
[3],
2021 guid
->guid
[4], guid
->guid
[5], guid
->guid
[6], guid
->guid
[7],
2022 guid
->guid
[8], guid
->guid
[9], guid
->guid
[10], guid
->guid
[11],
2023 guid
->guid
[12], guid
->guid
[13], guid
->guid
[14], guid
->guid
[15]);
2027 retryGetProviderData
= B_FALSE
;
2028 stmfRet
= stmfGetProviderDataProt("sbd", &nvl
,
2029 STMF_LU_PROVIDER_TYPE
, &setToken
);
2030 if (stmfRet
!= STMF_STATUS_SUCCESS
) {
2031 if (persist
&& stmfRet
== STMF_ERROR_NOT_FOUND
) {
2032 ret
= nvlist_alloc(&nvl
, NV_UNIQUE_NAME
, 0);
2035 "unpersistGuid:nvlist_alloc(%d)",
2037 ret
= STMF_STATUS_ERROR
;
2043 * if we're persisting the data, it's
2044 * an error. Otherwise, just return
2053 ret
= nvlist_add_string(nvl
, guidAsciiBuf
, filename
);
2055 ret
= nvlist_remove(nvl
, guidAsciiBuf
,
2057 if (ret
== ENOENT
) {
2063 stmfRet
= stmfSetProviderDataProt("sbd", nvl
,
2064 STMF_LU_PROVIDER_TYPE
, NULL
);
2066 stmfRet
= stmfSetProviderDataProt("sbd", nvl
,
2067 STMF_LU_PROVIDER_TYPE
, &setToken
);
2069 if (stmfRet
!= STMF_STATUS_SUCCESS
) {
2070 if (stmfRet
== STMF_ERROR_BUSY
) {
2071 /* get/set failed, try again */
2072 retryGetProviderData
= B_TRUE
;
2073 if (retryCnt
++ > MAX_PROVIDER_RETRY
) {
2078 } else if (stmfRet
==
2079 STMF_ERROR_PROV_DATA_STALE
) {
2080 /* update failed, try again */
2083 retryGetProviderData
= B_TRUE
;
2084 if (retryCnt
++ > MAX_PROVIDER_RETRY
) {
2091 "unpersistGuid:error(%x)", stmfRet
);
2098 "unpersistGuid:error nvlist_add/remove(%d)",
2100 ret
= STMF_STATUS_ERROR
;
2102 } while (retryGetProviderData
);
2113 * Purpose: Get current value for a resource property
2115 * hdl - luResource from a previous call to stmfCreateLuResource
2117 * resourceProp - a valid resource property type
2119 * propVal - void pointer to a pointer of the value to be retrieved
2122 stmfGetLuProp(luResource hdl
, uint32_t prop
, char *propVal
, size_t *propLen
)
2124 int ret
= STMF_STATUS_SUCCESS
;
2125 luResourceImpl
*luPropsHdl
= hdl
;
2126 if (hdl
== NULL
|| propLen
== NULL
|| propVal
== NULL
) {
2127 return (STMF_ERROR_INVALID_ARG
);
2130 if (luPropsHdl
->type
== STMF_DISK
) {
2131 ret
= getDiskProp(luPropsHdl
, prop
, propVal
, propLen
);
2133 return (STMF_ERROR_INVALID_ARG
);
2142 * Purpose: Get a logical unit resource handle for a given logical unit.
2144 * hdl - pointer to luResource
2147 stmfGetLuResource(stmfGuid
*luGuid
, luResource
*hdl
)
2149 int ret
= STMF_STATUS_SUCCESS
;
2150 stmfLogicalUnitProperties luProps
;
2153 return (STMF_ERROR_INVALID_ARG
);
2156 /* Check logical unit provider name to call correct dtype function */
2157 if ((ret
= stmfGetLogicalUnitProperties(luGuid
, &luProps
))
2158 != STMF_STATUS_SUCCESS
) {
2161 if (strcmp(luProps
.providerName
, "sbd") == 0) {
2162 ret
= getDiskAllProps(luGuid
, hdl
);
2163 } else if (luProps
.status
== STMF_LOGICAL_UNIT_UNREGISTERED
) {
2164 return (STMF_ERROR_NOT_FOUND
);
2166 return (STMF_ERROR_INVALID_ARG
);
2176 * Purpose: load all disk properties from sbd driver
2178 * luGuid - guid of disk device for which properties are to be retrieved
2179 * hdl - allocated luResource into which properties are to be copied
2183 getDiskAllProps(stmfGuid
*luGuid
, luResource
*hdl
)
2185 int ret
= STMF_STATUS_SUCCESS
;
2187 sbd_lu_props_t
*sbdProps
;
2190 int sbdPropsSize
= sizeof (*sbdProps
) + MAX_SBD_PROPS
;
2191 stmf_iocdata_t sbdIoctl
= {0};
2194 * Open control node for sbd
2196 if ((ret
= openSbd(OPEN_SBD
, &fd
)) != STMF_STATUS_SUCCESS
)
2200 *hdl
= calloc(1, sizeof (luResourceImpl
));
2203 return (STMF_ERROR_NOMEM
);
2206 sbdProps
= calloc(1, sbdPropsSize
);
2207 if (sbdProps
== NULL
) {
2210 return (STMF_ERROR_NOMEM
);
2213 ret
= createDiskResource((luResourceImpl
*)*hdl
);
2214 if (ret
!= STMF_STATUS_SUCCESS
) {
2221 sbdProps
->slp_input_guid
= 1;
2222 bcopy(luGuid
, sbdProps
->slp_guid
, sizeof (sbdProps
->slp_guid
));
2224 sbdIoctl
.stmf_version
= STMF_VERSION_1
;
2225 sbdIoctl
.stmf_ibuf_size
= sbdPropsSize
;
2226 sbdIoctl
.stmf_ibuf
= (uint64_t)(unsigned long)sbdProps
;
2227 sbdIoctl
.stmf_obuf_size
= sbdPropsSize
;
2228 sbdIoctl
.stmf_obuf
= (uint64_t)(unsigned long)sbdProps
;
2229 ioctlRet
= ioctl(fd
, SBD_IOCTL_GET_LU_PROPS
, &sbdIoctl
);
2230 if (ioctlRet
!= 0) {
2232 switch (savedErrno
) {
2234 ret
= STMF_ERROR_BUSY
;
2238 ret
= STMF_ERROR_PERM
;
2241 ret
= STMF_ERROR_NOT_FOUND
;
2245 "getDiskAllProps:ioctl error(%d) (%d) (%d)",
2246 ioctlRet
, sbdIoctl
.stmf_error
, savedErrno
);
2247 ret
= STMF_STATUS_ERROR
;
2252 if (ret
== STMF_STATUS_SUCCESS
) {
2253 ret
= loadDiskPropsFromDriver((luResourceImpl
*)*hdl
, sbdProps
);
2262 * loadDiskPropsFromDriver
2264 * Purpose: Retrieve all disk type properties from sbd driver
2266 * hdl - Allocated luResourceImpl
2267 * sbdProps - sbd_lu_props_t structure returned from sbd driver
2271 loadDiskPropsFromDriver(luResourceImpl
*hdl
, sbd_lu_props_t
*sbdProps
)
2273 int ret
= STMF_STATUS_SUCCESS
;
2274 diskResource
*diskLu
= hdl
->resource
;
2276 diskLu
->luGuidValid
= B_TRUE
;
2277 bcopy(sbdProps
->slp_guid
, diskLu
->luGuid
, sizeof (sbdProps
->slp_guid
));
2279 if (sbdProps
->slp_separate_meta
&& sbdProps
->slp_meta_fname_valid
) {
2280 diskLu
->luMetaFileNameValid
= B_TRUE
;
2281 if (strlcpy(diskLu
->luMetaFileName
,
2282 (char *)&(sbdProps
->slp_buf
[sbdProps
->slp_meta_fname_off
]),
2283 sizeof (diskLu
->luMetaFileName
)) >=
2284 sizeof (diskLu
->luMetaFileName
)) {
2285 return (STMF_STATUS_ERROR
);
2289 if (sbdProps
->slp_data_fname_valid
) {
2290 diskLu
->luDataFileNameValid
= B_TRUE
;
2291 if (strlcpy(diskLu
->luDataFileName
,
2292 (char *)&(sbdProps
->slp_buf
[sbdProps
->slp_data_fname_off
]),
2293 sizeof (diskLu
->luDataFileName
)) >=
2294 sizeof (diskLu
->luDataFileName
)) {
2295 return (STMF_STATUS_ERROR
);
2299 if (sbdProps
->slp_serial_valid
) {
2300 diskLu
->serialNumValid
= B_TRUE
;
2301 bcopy(&(sbdProps
->slp_buf
[sbdProps
->slp_serial_off
]),
2302 diskLu
->serialNum
, sbdProps
->slp_serial_size
);
2305 if (sbdProps
->slp_mgmt_url_valid
) {
2306 diskLu
->luMgmtUrlValid
= B_TRUE
;
2307 if (strlcpy(diskLu
->luMgmtUrl
,
2308 (char *)&(sbdProps
->slp_buf
[sbdProps
->slp_mgmt_url_off
]),
2309 sizeof (diskLu
->luMgmtUrl
)) >=
2310 sizeof (diskLu
->luMgmtUrl
)) {
2311 return (STMF_STATUS_ERROR
);
2315 if (sbdProps
->slp_alias_valid
) {
2316 diskLu
->luAliasValid
= B_TRUE
;
2317 if (strlcpy(diskLu
->luAlias
,
2318 (char *)&(sbdProps
->slp_buf
[sbdProps
->slp_alias_off
]),
2319 sizeof (diskLu
->luAlias
)) >=
2320 sizeof (diskLu
->luAlias
)) {
2321 return (STMF_STATUS_ERROR
);
2323 } else { /* set alias to data filename if not set */
2324 if (sbdProps
->slp_data_fname_valid
) {
2325 diskLu
->luAliasValid
= B_TRUE
;
2326 if (strlcpy(diskLu
->luAlias
,
2327 (char *)&(sbdProps
->slp_buf
[
2328 sbdProps
->slp_data_fname_off
]),
2329 sizeof (diskLu
->luAlias
)) >=
2330 sizeof (diskLu
->luAlias
)) {
2331 return (STMF_STATUS_ERROR
);
2336 diskLu
->vidValid
= B_TRUE
;
2337 bcopy(sbdProps
->slp_vid
, diskLu
->vid
, sizeof (diskLu
->vid
));
2339 diskLu
->pidValid
= B_TRUE
;
2340 bcopy(sbdProps
->slp_pid
, diskLu
->pid
, sizeof (diskLu
->pid
));
2342 diskLu
->revValid
= B_TRUE
;
2343 bcopy(sbdProps
->slp_rev
, diskLu
->rev
, sizeof (diskLu
->rev
));
2345 diskLu
->writeProtectEnableValid
= B_TRUE
;
2346 if (sbdProps
->slp_write_protected
) {
2347 diskLu
->writeProtectEnable
= B_TRUE
;
2350 diskLu
->writebackCacheDisableValid
= B_TRUE
;
2351 if (sbdProps
->slp_writeback_cache_disable_cur
) {
2352 diskLu
->writebackCacheDisable
= B_TRUE
;
2355 diskLu
->blkSizeValid
= B_TRUE
;
2356 diskLu
->blkSize
= sbdProps
->slp_blksize
;
2358 diskLu
->luSizeValid
= B_TRUE
;
2359 diskLu
->luSize
= sbdProps
->slp_lu_size
;
2361 diskLu
->accessState
= sbdProps
->slp_access_state
;
2367 * stmfGetGlobalLuProp
2369 * Purpose: get a global property for a device type
2373 stmfGetGlobalLuProp(uint16_t dType
, uint32_t prop
, char *propVal
,
2376 int ret
= STMF_STATUS_SUCCESS
;
2377 if (dType
!= STMF_DISK
|| propVal
== NULL
) {
2378 return (STMF_ERROR_INVALID_ARG
);
2381 ret
= getDiskGlobalProp(prop
, propVal
, propLen
);
2389 * Purpose: get global property from sbd driver
2393 getDiskGlobalProp(uint32_t prop
, char *propVal
, size_t *propLen
)
2395 int ret
= STMF_STATUS_SUCCESS
;
2397 sbd_global_props_t
*sbdProps
;
2403 int sbdPropsSize
= sizeof (*sbdProps
) + MAX_SBD_PROPS
;
2404 stmf_iocdata_t sbdIoctl
= {0};
2408 case STMF_LU_PROP_MGMT_URL
:
2411 return (STMF_ERROR_INVALID_PROP
);
2415 * Open control node for sbd
2417 if ((ret
= openSbd(OPEN_SBD
, &fd
)) != STMF_STATUS_SUCCESS
)
2420 sbdProps
= calloc(1, sbdPropsSize
);
2421 if (sbdProps
== NULL
) {
2423 return (STMF_ERROR_NOMEM
);
2428 sbdIoctl
.stmf_version
= STMF_VERSION_1
;
2429 sbdIoctl
.stmf_obuf_size
= sbdPropsSize
;
2430 sbdIoctl
.stmf_obuf
= (uint64_t)(unsigned long)sbdProps
;
2431 ioctlRet
= ioctl(fd
, SBD_IOCTL_GET_GLOBAL_LU
, &sbdIoctl
);
2432 if (ioctlRet
!= 0) {
2434 switch (savedErrno
) {
2436 ret
= STMF_ERROR_BUSY
;
2440 ret
= STMF_ERROR_PERM
;
2443 if (sbdIoctl
.stmf_error
==
2444 SBD_RET_INSUFFICIENT_BUF_SPACE
&&
2447 sizeof (*sbdProps
) +
2449 mlu_buf_size_needed
;
2451 sbd_realloc
= sbdProps
;
2452 sbdProps
= realloc(sbdProps
,
2454 if (sbdProps
== NULL
) {
2456 ret
= STMF_ERROR_NOMEM
;
2461 ret
= STMF_ERROR_NOMEM
;
2466 "getDiskGlobalProp:ioctl error(%d)"
2467 "(%d)(%d)", ioctlRet
,
2468 sbdIoctl
.stmf_error
, savedErrno
);
2469 ret
= STMF_STATUS_ERROR
;
2476 if (ret
!= STMF_STATUS_SUCCESS
) {
2481 case STMF_LU_PROP_MGMT_URL
:
2482 if (sbdProps
->mlu_mgmt_url_valid
== 0) {
2483 ret
= STMF_ERROR_NO_PROP
;
2486 if ((reqLen
= strlcpy(propVal
, (char *)&(
2487 sbdProps
->mlu_buf
[sbdProps
->mlu_mgmt_url_off
]),
2488 *propLen
)) >= *propLen
) {
2489 *propLen
= reqLen
+ 1;
2490 ret
= STMF_ERROR_INVALID_ARG
;
2503 * stmfSetGlobalLuProp
2505 * Purpose: set a global property for a device type
2509 stmfSetGlobalLuProp(uint16_t dType
, uint32_t prop
, const char *propVal
)
2511 int ret
= STMF_STATUS_SUCCESS
;
2512 if (dType
!= STMF_DISK
|| propVal
== NULL
) {
2513 return (STMF_ERROR_INVALID_ARG
);
2516 ret
= setDiskGlobalProp(prop
, propVal
);
2524 * Purpose: set properties for resource of type disk
2526 * resourceProp - valid resource identifier
2527 * propVal - valid resource value
2530 setDiskGlobalProp(uint32_t resourceProp
, const char *propVal
)
2532 int ret
= STMF_STATUS_SUCCESS
;
2533 sbd_global_props_t
*sbdGlobalProps
= NULL
;
2534 int sbdGlobalPropsSize
= 0;
2540 stmf_iocdata_t sbdIoctl
= {0};
2542 switch (resourceProp
) {
2543 case STMF_LU_PROP_MGMT_URL
:
2546 return (STMF_ERROR_INVALID_PROP
);
2550 * Open control node for sbd
2552 if ((ret
= openSbd(OPEN_SBD
, &fd
)) != STMF_STATUS_SUCCESS
)
2555 propLen
= strlen(propVal
);
2556 mluBufSize
+= propLen
+ 1;
2557 sbdGlobalPropsSize
+= sizeof (sbd_global_props_t
) - 8 +
2560 * 8 is the size of the buffer set aside for
2561 * concatenation of variable length fields
2563 sbdGlobalProps
= (sbd_global_props_t
*)calloc(1, sbdGlobalPropsSize
);
2564 if (sbdGlobalProps
== NULL
) {
2566 return (STMF_ERROR_NOMEM
);
2569 sbdGlobalProps
->mlu_struct_size
= sbdGlobalPropsSize
;
2571 switch (resourceProp
) {
2572 case STMF_LU_PROP_MGMT_URL
:
2573 sbdGlobalProps
->mlu_mgmt_url_valid
= 1;
2574 bcopy(propVal
, &(sbdGlobalProps
->mlu_buf
),
2578 ret
= STMF_ERROR_NO_PROP
;
2582 sbdIoctl
.stmf_version
= STMF_VERSION_1
;
2583 sbdIoctl
.stmf_ibuf_size
= sbdGlobalProps
->mlu_struct_size
;
2584 sbdIoctl
.stmf_ibuf
= (uint64_t)(unsigned long)sbdGlobalProps
;
2586 ioctlRet
= ioctl(fd
, SBD_IOCTL_SET_GLOBAL_LU
, &sbdIoctl
);
2587 if (ioctlRet
!= 0) {
2589 switch (savedErrno
) {
2591 ret
= STMF_ERROR_BUSY
;
2595 ret
= STMF_ERROR_PERM
;
2598 diskError(sbdIoctl
.stmf_error
, &ret
);
2599 if (ret
== STMF_STATUS_ERROR
) {
2601 "modifyDiskLu:ioctl "
2602 "error(%d) (%d) (%d)", ioctlRet
,
2603 sbdIoctl
.stmf_error
, savedErrno
);
2610 free(sbdGlobalProps
);
2619 * Purpose: set a property on an luResource
2621 * hdl - allocated luResource
2622 * prop - property identifier
2623 * propVal - property value to be set
2626 stmfSetLuProp(luResource hdl
, uint32_t prop
, const char *propVal
)
2628 int ret
= STMF_STATUS_SUCCESS
;
2629 luResourceImpl
*luPropsHdl
= hdl
;
2631 return (STMF_ERROR_INVALID_ARG
);
2634 if (luPropsHdl
->type
== STMF_DISK
) {
2635 ret
= setDiskProp(luPropsHdl
, prop
, propVal
);
2637 return (STMF_ERROR_INVALID_ARG
);
2646 * Purpose: retrieve a given property from a logical unit resource of type disk
2648 * hdl - allocated luResourceImpl
2649 * prop - property identifier
2650 * propVal - pointer to character to contain the retrieved property value
2651 * propLen - On input this is the length of propVal. On failure, it contains the
2652 * number of bytes required for propVal
2655 getDiskProp(luResourceImpl
*hdl
, uint32_t prop
, char *propVal
, size_t *propLen
)
2657 int ret
= STMF_STATUS_SUCCESS
;
2658 diskResource
*diskLu
= hdl
->resource
;
2659 char accessState
[20];
2662 if (prop
== STMF_LU_PROP_ACCESS_STATE
) {
2663 if (diskLu
->accessState
== SBD_LU_ACTIVE
) {
2664 (void) strlcpy(accessState
, STMF_ACCESS_ACTIVE
,
2665 sizeof (accessState
));
2666 } else if (diskLu
->accessState
== SBD_LU_TRANSITION_TO_ACTIVE
) {
2667 (void) strlcpy(accessState
,
2668 STMF_ACCESS_STANDBY_TO_ACTIVE
,
2669 sizeof (accessState
));
2670 } else if (diskLu
->accessState
== SBD_LU_STANDBY
) {
2671 (void) strlcpy(accessState
, STMF_ACCESS_STANDBY
,
2672 sizeof (accessState
));
2673 } else if (diskLu
->accessState
==
2674 SBD_LU_TRANSITION_TO_STANDBY
) {
2675 (void) strlcpy(accessState
,
2676 STMF_ACCESS_ACTIVE_TO_STANDBY
,
2677 sizeof (accessState
));
2679 if ((reqLen
= strlcpy(propVal
, accessState
,
2680 *propLen
)) >= *propLen
) {
2681 *propLen
= reqLen
+ 1;
2682 return (STMF_ERROR_INVALID_ARG
);
2687 if (diskLu
->accessState
!= SBD_LU_ACTIVE
) {
2688 return (STMF_ERROR_NO_PROP_STANDBY
);
2692 case STMF_LU_PROP_BLOCK_SIZE
:
2693 if (diskLu
->blkSizeValid
== B_FALSE
) {
2694 return (STMF_ERROR_NO_PROP
);
2696 reqLen
= snprintf(propVal
, *propLen
, "%llu",
2697 (u_longlong_t
)diskLu
->blkSize
);
2698 if (reqLen
>= *propLen
) {
2699 *propLen
= reqLen
+ 1;
2700 return (STMF_ERROR_INVALID_ARG
);
2703 case STMF_LU_PROP_FILENAME
:
2704 if (diskLu
->luDataFileNameValid
== B_FALSE
) {
2705 return (STMF_ERROR_NO_PROP
);
2707 if ((reqLen
= strlcpy(propVal
, diskLu
->luDataFileName
,
2708 *propLen
)) >= *propLen
) {
2709 *propLen
= reqLen
+ 1;
2710 return (STMF_ERROR_INVALID_ARG
);
2713 case STMF_LU_PROP_META_FILENAME
:
2714 if (diskLu
->luMetaFileNameValid
== B_FALSE
) {
2715 return (STMF_ERROR_NO_PROP
);
2717 if ((reqLen
= strlcpy(propVal
, diskLu
->luMetaFileName
,
2718 *propLen
)) >= *propLen
) {
2719 *propLen
= reqLen
+ 1;
2720 return (STMF_ERROR_INVALID_ARG
);
2723 case STMF_LU_PROP_MGMT_URL
:
2724 if (diskLu
->luMgmtUrlValid
== B_FALSE
) {
2725 return (STMF_ERROR_NO_PROP
);
2727 if ((reqLen
= strlcpy(propVal
, diskLu
->luMgmtUrl
,
2728 *propLen
)) >= *propLen
) {
2729 *propLen
= reqLen
+ 1;
2730 return (STMF_ERROR_INVALID_ARG
);
2733 case STMF_LU_PROP_GUID
:
2734 if (diskLu
->luGuidValid
== B_FALSE
) {
2735 return (STMF_ERROR_NO_PROP
);
2737 reqLen
= snprintf(propVal
, *propLen
,
2738 "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X"
2740 diskLu
->luGuid
[0], diskLu
->luGuid
[1],
2741 diskLu
->luGuid
[2], diskLu
->luGuid
[3],
2742 diskLu
->luGuid
[4], diskLu
->luGuid
[5],
2743 diskLu
->luGuid
[6], diskLu
->luGuid
[7],
2744 diskLu
->luGuid
[8], diskLu
->luGuid
[9],
2745 diskLu
->luGuid
[10], diskLu
->luGuid
[11],
2746 diskLu
->luGuid
[12], diskLu
->luGuid
[13],
2747 diskLu
->luGuid
[14], diskLu
->luGuid
[15]);
2748 if (reqLen
>= *propLen
) {
2749 *propLen
= reqLen
+ 1;
2750 return (STMF_ERROR_INVALID_ARG
);
2753 case STMF_LU_PROP_SERIAL_NUM
:
2754 if (diskLu
->serialNumValid
== B_FALSE
) {
2755 return (STMF_ERROR_NO_PROP
);
2757 if ((reqLen
= strlcpy(propVal
, diskLu
->serialNum
,
2758 *propLen
)) >= *propLen
) {
2759 *propLen
= reqLen
+ 1;
2760 return (STMF_ERROR_INVALID_ARG
);
2763 case STMF_LU_PROP_SIZE
:
2764 if (diskLu
->luSizeValid
== B_FALSE
) {
2765 return (STMF_ERROR_NO_PROP
);
2767 (void) snprintf(propVal
, *propLen
, "%llu",
2768 (u_longlong_t
)diskLu
->luSize
);
2770 case STMF_LU_PROP_ALIAS
:
2771 if (diskLu
->luAliasValid
== B_FALSE
) {
2772 return (STMF_ERROR_NO_PROP
);
2774 if ((reqLen
= strlcpy(propVal
, diskLu
->luAlias
,
2775 *propLen
)) >= *propLen
) {
2776 *propLen
= reqLen
+ 1;
2777 return (STMF_ERROR_INVALID_ARG
);
2780 case STMF_LU_PROP_VID
:
2781 if (diskLu
->vidValid
== B_FALSE
) {
2782 return (STMF_ERROR_NO_PROP
);
2784 if (*propLen
<= sizeof (diskLu
->vid
)) {
2785 return (STMF_ERROR_INVALID_ARG
);
2787 bcopy(diskLu
->vid
, propVal
, sizeof (diskLu
->vid
));
2788 propVal
[sizeof (diskLu
->vid
)] = 0;
2790 case STMF_LU_PROP_PID
:
2791 if (diskLu
->pidValid
== B_FALSE
) {
2792 return (STMF_ERROR_NO_PROP
);
2794 if (*propLen
<= sizeof (diskLu
->pid
)) {
2795 return (STMF_ERROR_INVALID_ARG
);
2797 bcopy(diskLu
->pid
, propVal
, sizeof (diskLu
->pid
));
2798 propVal
[sizeof (diskLu
->pid
)] = 0;
2800 case STMF_LU_PROP_WRITE_PROTECT
:
2801 if (diskLu
->writeProtectEnableValid
== B_FALSE
) {
2802 return (STMF_ERROR_NO_PROP
);
2804 if (diskLu
->writeProtectEnable
) {
2805 if ((reqLen
= strlcpy(propVal
, "true",
2806 *propLen
)) >= *propLen
) {
2807 *propLen
= reqLen
+ 1;
2808 return (STMF_ERROR_INVALID_ARG
);
2811 if ((reqLen
= strlcpy(propVal
, "false",
2812 *propLen
)) >= *propLen
) {
2813 *propLen
= reqLen
+ 1;
2814 return (STMF_ERROR_INVALID_ARG
);
2818 case STMF_LU_PROP_WRITE_CACHE_DISABLE
:
2819 if (diskLu
->writebackCacheDisableValid
== B_FALSE
) {
2820 return (STMF_ERROR_NO_PROP
);
2822 if (diskLu
->writebackCacheDisable
) {
2823 if ((reqLen
= strlcpy(propVal
, "true",
2824 *propLen
)) >= *propLen
) {
2825 *propLen
= reqLen
+ 1;
2826 return (STMF_ERROR_INVALID_ARG
);
2829 if ((reqLen
= strlcpy(propVal
, "false",
2830 *propLen
)) >= *propLen
) {
2831 *propLen
= reqLen
+ 1;
2832 return (STMF_ERROR_INVALID_ARG
);
2837 ret
= STMF_ERROR_INVALID_PROP
;
2847 * Purpose: set properties for resource of type disk
2849 * hdl - allocated luResourceImpl
2850 * resourceProp - valid resource identifier
2851 * propVal - valid resource value
2854 setDiskProp(luResourceImpl
*hdl
, uint32_t resourceProp
, const char *propVal
)
2856 int ret
= STMF_STATUS_SUCCESS
;
2858 diskResource
*diskLu
= hdl
->resource
;
2859 unsigned long long numericProp
= 0;
2860 char guidProp
[LU_ASCII_GUID_SIZE
+ 1];
2861 char ouiProp
[OUI_ASCII_SIZE
+ 1];
2862 char hostIdProp
[HOST_ID_ASCII_SIZE
+ 1];
2863 unsigned int oui
[OUI_SIZE
];
2864 unsigned int hostId
[HOST_ID_SIZE
];
2865 unsigned int guid
[LU_GUID_SIZE
];
2869 if (propVal
== NULL
) {
2870 return (STMF_ERROR_INVALID_ARG
);
2873 switch (resourceProp
) {
2874 case STMF_LU_PROP_ALIAS
:
2875 if (strlcpy(diskLu
->luAlias
, propVal
,
2876 sizeof (diskLu
->luAlias
)) >=
2877 sizeof (diskLu
->luAlias
)) {
2878 return (STMF_ERROR_INVALID_PROPSIZE
);
2880 diskLu
->luAliasValid
= B_TRUE
;
2882 case STMF_LU_PROP_BLOCK_SIZE
: {
2883 const char *tmp
= propVal
;
2885 if (!isdigit(*tmp
++)) {
2886 return (STMF_ERROR_INVALID_ARG
);
2889 (void) sscanf(propVal
, "%llu", &numericProp
);
2890 if (numericProp
> UINT16_MAX
) {
2891 return (STMF_ERROR_INVALID_PROPSIZE
);
2893 diskLu
->blkSize
= numericProp
;
2894 diskLu
->blkSizeValid
= B_TRUE
;
2897 case STMF_LU_PROP_COMPANY_ID
:
2898 if ((strlcpy(ouiProp
, propVal
, sizeof (ouiProp
))) >=
2900 return (STMF_ERROR_INVALID_ARG
);
2902 if (checkHexUpper(ouiProp
) != 0) {
2903 return (STMF_ERROR_INVALID_ARG
);
2905 (void) sscanf(ouiProp
, "%2X%2X%2X",
2906 &oui
[0], &oui
[1], &oui
[2]);
2908 diskLu
->companyId
= 0;
2909 diskLu
->companyId
+= oui
[0] << 16;
2910 diskLu
->companyId
+= oui
[1] << 8;
2911 diskLu
->companyId
+= oui
[2];
2912 if (diskLu
->companyId
== 0) {
2913 return (STMF_ERROR_INVALID_ARG
);
2915 diskLu
->companyIdValid
= B_TRUE
;
2917 case STMF_LU_PROP_HOST_ID
:
2918 if ((strlcpy(hostIdProp
, propVal
,
2919 sizeof (hostIdProp
))) >= sizeof (hostIdProp
)) {
2920 return (STMF_ERROR_INVALID_ARG
);
2922 if (checkHexUpper(hostIdProp
) != 0) {
2923 return (STMF_ERROR_INVALID_ARG
);
2925 (void) sscanf(hostIdProp
, "%2X%2X%2X%2X",
2926 &hostId
[0], &hostId
[1], &hostId
[2], &hostId
[3]);
2929 diskLu
->hostId
+= hostId
[0] << 24;
2930 diskLu
->hostId
+= hostId
[1] << 16;
2931 diskLu
->hostId
+= hostId
[2] << 8;
2932 diskLu
->hostId
+= hostId
[3];
2933 if (diskLu
->hostId
== 0) {
2934 return (STMF_ERROR_INVALID_ARG
);
2936 diskLu
->hostIdValid
= B_TRUE
;
2938 case STMF_LU_PROP_GUID
:
2939 if (strlen(propVal
) != LU_ASCII_GUID_SIZE
) {
2940 return (STMF_ERROR_INVALID_PROPSIZE
);
2943 if ((strlcpy(guidProp
, propVal
, sizeof (guidProp
))) >=
2944 sizeof (guidProp
)) {
2945 return (STMF_ERROR_INVALID_ARG
);
2948 if (checkHexUpper(guidProp
) != 0) {
2949 return (STMF_ERROR_INVALID_ARG
);
2952 (void) sscanf(guidProp
,
2953 "%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X",
2954 &guid
[0], &guid
[1], &guid
[2], &guid
[3], &guid
[4],
2955 &guid
[5], &guid
[6], &guid
[7], &guid
[8], &guid
[9],
2956 &guid
[10], &guid
[11], &guid
[12], &guid
[13],
2957 &guid
[14], &guid
[15]);
2958 for (i
= 0; i
< sizeof (diskLu
->luGuid
); i
++) {
2959 diskLu
->luGuid
[i
] = guid
[i
];
2961 diskLu
->luGuidValid
= B_TRUE
;
2963 case STMF_LU_PROP_FILENAME
:
2964 if ((strlcpy(diskLu
->luDataFileName
, propVal
,
2965 sizeof (diskLu
->luDataFileName
))) >=
2966 sizeof (diskLu
->luDataFileName
)) {
2967 return (STMF_ERROR_INVALID_PROPSIZE
);
2969 diskLu
->luDataFileNameValid
= B_TRUE
;
2971 case STMF_LU_PROP_META_FILENAME
:
2972 if ((strlcpy(diskLu
->luMetaFileName
, propVal
,
2973 sizeof (diskLu
->luMetaFileName
))) >=
2974 sizeof (diskLu
->luMetaFileName
)) {
2975 return (STMF_ERROR_INVALID_PROPSIZE
);
2977 diskLu
->luMetaFileNameValid
= B_TRUE
;
2979 case STMF_LU_PROP_MGMT_URL
:
2980 if ((strlcpy(diskLu
->luMgmtUrl
, propVal
,
2981 sizeof (diskLu
->luMgmtUrl
))) >=
2982 sizeof (diskLu
->luMgmtUrl
)) {
2983 return (STMF_ERROR_INVALID_PROPSIZE
);
2985 diskLu
->luMgmtUrlValid
= B_TRUE
;
2987 case STMF_LU_PROP_PID
:
2988 if ((propSize
= strlen(propVal
)) >
2989 sizeof (diskLu
->pid
)) {
2990 return (STMF_ERROR_INVALID_PROPSIZE
);
2992 (void) strncpy(diskLu
->pid
, propVal
, propSize
);
2993 diskLu
->pidValid
= B_TRUE
;
2995 case STMF_LU_PROP_SERIAL_NUM
:
2996 if ((propSize
= strlen(propVal
)) >
2997 (sizeof (diskLu
->serialNum
) - 1)) {
2998 return (STMF_ERROR_INVALID_PROPSIZE
);
3000 (void) strncpy(diskLu
->serialNum
, propVal
, propSize
);
3001 diskLu
->serialNumValid
= B_TRUE
;
3003 case STMF_LU_PROP_SIZE
:
3004 if ((niceStrToNum(propVal
, &diskLu
->luSize
) != 0)) {
3005 return (STMF_ERROR_INVALID_ARG
);
3007 diskLu
->luSizeValid
= B_TRUE
;
3009 case STMF_LU_PROP_VID
:
3010 if ((propSize
= strlen(propVal
)) >
3011 sizeof (diskLu
->vid
)) {
3012 return (STMF_ERROR_INVALID_PROPSIZE
);
3014 (void) strncpy(diskLu
->vid
, propVal
, propSize
);
3015 diskLu
->vidValid
= B_TRUE
;
3017 case STMF_LU_PROP_WRITE_PROTECT
:
3018 if (strcasecmp(propVal
, "TRUE") == 0) {
3019 diskLu
->writeProtectEnable
= B_TRUE
;
3020 } else if (strcasecmp(propVal
, "FALSE") == 0) {
3021 diskLu
->writeProtectEnable
= B_FALSE
;
3023 return (STMF_ERROR_INVALID_ARG
);
3025 diskLu
->writeProtectEnableValid
= B_TRUE
;
3027 case STMF_LU_PROP_WRITE_CACHE_DISABLE
:
3028 if (strcasecmp(propVal
, "TRUE") == 0) {
3029 diskLu
->writebackCacheDisable
= B_TRUE
;
3030 } else if (strcasecmp(propVal
, "FALSE") == 0) {
3031 diskLu
->writebackCacheDisable
= B_FALSE
;
3033 return (STMF_ERROR_INVALID_ARG
);
3035 diskLu
->writebackCacheDisableValid
= B_TRUE
;
3037 case STMF_LU_PROP_ACCESS_STATE
:
3038 ret
= STMF_ERROR_INVALID_PROP
;
3041 ret
= STMF_ERROR_INVALID_PROP
;
3048 checkHexUpper(char *buf
)
3052 for (i
= 0; i
< strlen(buf
); i
++) {
3053 if (isxdigit(buf
[i
])) {
3054 buf
[i
] = toupper(buf
[i
]);
3064 * Given a numeric suffix, convert the value into a number of bits that the
3065 * resulting value must be shifted.
3066 * Code lifted from libzfs_util.c
3069 strToShift(const char *buf
)
3071 const char *ends
= "BKMGTPE";
3077 for (i
= 0; i
< strlen(ends
); i
++) {
3078 if (toupper(buf
[0]) == ends
[i
])
3086 stmfFreeLuResource(luResource hdl
)
3088 int ret
= STMF_STATUS_SUCCESS
;
3090 return (STMF_ERROR_INVALID_ARG
);
3093 luResourceImpl
*hdlImpl
= hdl
;
3094 free(hdlImpl
->resource
);
3100 * Convert a string of the form '100G' into a real number. Used when setting
3101 * the size of a logical unit.
3102 * Code lifted from libzfs_util.c
3105 niceStrToNum(const char *value
, uint64_t *num
)
3112 /* Check to see if this looks like a number. */
3113 if ((value
[0] < '0' || value
[0] > '9') && value
[0] != '.') {
3117 /* Rely on stroull() to process the numeric portion. */
3119 *num
= strtoull(value
, &end
, 10);
3122 * Check for ERANGE, which indicates that the value is too large to fit
3123 * in a 64-bit value.
3125 if (errno
== ERANGE
) {
3130 * If we have a decimal value, then do the computation with floating
3131 * point arithmetic. Otherwise, use standard arithmetic.
3134 double fval
= strtod(value
, &end
);
3136 if ((shift
= strToShift(end
)) == -1) {
3140 fval
*= pow(2, shift
);
3142 if (fval
> UINT64_MAX
) {
3146 *num
= (uint64_t)fval
;
3148 if ((shift
= strToShift(end
)) == -1) {
3152 /* Check for overflow */
3153 if (shift
>= 64 || (*num
<< shift
) >> shift
!= *num
) {
3164 * stmfCreateTargetGroup
3166 * Purpose: Create a local port group
3168 * targetGroupName - name of local port group to create
3171 stmfCreateTargetGroup(stmfGroupName
*targetGroupName
)
3176 if (targetGroupName
== NULL
||
3177 (strnlen((char *)targetGroupName
, sizeof (stmfGroupName
))
3178 == sizeof (stmfGroupName
))) {
3179 return (STMF_ERROR_INVALID_ARG
);
3182 /* Check to ensure service exists */
3183 if (psCheckService() != STMF_STATUS_SUCCESS
) {
3184 return (STMF_ERROR_SERVICE_NOT_FOUND
);
3188 ret
= initializeConfig();
3189 if (ret
!= STMF_STATUS_SUCCESS
) {
3194 * Open control node for stmf
3196 if ((ret
= openStmf(OPEN_STMF
, &fd
)) != STMF_STATUS_SUCCESS
)
3200 * Add the group to the driver
3202 if ((ret
= groupIoctl(fd
, STMF_IOCTL_CREATE_TARGET_GROUP
,
3203 targetGroupName
)) != STMF_STATUS_SUCCESS
) {
3207 if (iGetPersistMethod() == STMF_PERSIST_NONE
) {
3212 * If the add to the driver was successful, add it to the persistent
3215 ret
= psCreateTargetGroup((char *)targetGroupName
);
3217 case STMF_PS_SUCCESS
:
3218 ret
= STMF_STATUS_SUCCESS
;
3220 case STMF_PS_ERROR_EXISTS
:
3221 ret
= STMF_ERROR_EXISTS
;
3223 case STMF_PS_ERROR_BUSY
:
3224 ret
= STMF_ERROR_BUSY
;
3226 case STMF_PS_ERROR_SERVICE_NOT_FOUND
:
3227 ret
= STMF_ERROR_SERVICE_NOT_FOUND
;
3229 case STMF_PS_ERROR_VERSION_MISMATCH
:
3230 ret
= STMF_ERROR_SERVICE_DATA_VERSION
;
3234 "stmfCreateTargetGroup:psCreateTargetGroup"
3236 ret
= STMF_STATUS_ERROR
;
3246 * stmfDeleteHostGroup
3248 * Purpose: Delete an initiator or local port group
3250 * hostGroupName - group to delete
3253 stmfDeleteHostGroup(stmfGroupName
*hostGroupName
)
3258 if (hostGroupName
== NULL
) {
3259 return (STMF_ERROR_INVALID_ARG
);
3262 /* Check to ensure service exists */
3263 if (psCheckService() != STMF_STATUS_SUCCESS
) {
3264 return (STMF_ERROR_SERVICE_NOT_FOUND
);
3268 ret
= initializeConfig();
3269 if (ret
!= STMF_STATUS_SUCCESS
) {
3274 * Open control node for stmf
3276 if ((ret
= openStmf(OPEN_STMF
, &fd
)) != STMF_STATUS_SUCCESS
)
3280 * Remove the group from the driver
3282 if ((ret
= groupIoctl(fd
, STMF_IOCTL_REMOVE_HOST_GROUP
,
3283 hostGroupName
)) != STMF_STATUS_SUCCESS
) {
3287 if (iGetPersistMethod() == STMF_PERSIST_NONE
) {
3292 * If the remove from the driver was successful, remove it from the
3295 ret
= psDeleteHostGroup((char *)hostGroupName
);
3297 case STMF_PS_SUCCESS
:
3298 ret
= STMF_STATUS_SUCCESS
;
3300 case STMF_PS_ERROR_NOT_FOUND
:
3301 ret
= STMF_ERROR_NOT_FOUND
;
3303 case STMF_PS_ERROR_BUSY
:
3304 ret
= STMF_ERROR_BUSY
;
3306 case STMF_PS_ERROR_SERVICE_NOT_FOUND
:
3307 ret
= STMF_ERROR_SERVICE_NOT_FOUND
;
3309 case STMF_PS_ERROR_VERSION_MISMATCH
:
3310 ret
= STMF_ERROR_SERVICE_DATA_VERSION
;
3314 "stmfDeleteHostGroup:psDeleteHostGroup:error(%d)",
3316 ret
= STMF_STATUS_ERROR
;
3326 * stmfDeleteTargetGroup
3328 * Purpose: Delete an initiator or local port group
3330 * targetGroupName - group to delete
3333 stmfDeleteTargetGroup(stmfGroupName
*targetGroupName
)
3335 int ret
= STMF_STATUS_SUCCESS
;
3338 if (targetGroupName
== NULL
) {
3339 return (STMF_ERROR_INVALID_ARG
);
3342 /* Check to ensure service exists */
3343 if (psCheckService() != STMF_STATUS_SUCCESS
) {
3344 return (STMF_ERROR_SERVICE_NOT_FOUND
);
3348 ret
= initializeConfig();
3349 if (ret
!= STMF_STATUS_SUCCESS
) {
3354 * Open control node for stmf
3356 if ((ret
= openStmf(OPEN_STMF
, &fd
)) != STMF_STATUS_SUCCESS
)
3360 * Remove the group from the driver
3362 if ((ret
= groupIoctl(fd
, STMF_IOCTL_REMOVE_TARGET_GROUP
,
3363 targetGroupName
)) != STMF_STATUS_SUCCESS
) {
3367 if (iGetPersistMethod() == STMF_PERSIST_NONE
) {
3372 * If the remove from the driver was successful, remove it from the
3375 ret
= psDeleteTargetGroup((char *)targetGroupName
);
3377 case STMF_PS_SUCCESS
:
3378 ret
= STMF_STATUS_SUCCESS
;
3380 case STMF_PS_ERROR_NOT_FOUND
:
3381 ret
= STMF_ERROR_NOT_FOUND
;
3383 case STMF_PS_ERROR_BUSY
:
3384 ret
= STMF_ERROR_BUSY
;
3386 case STMF_PS_ERROR_SERVICE_NOT_FOUND
:
3387 ret
= STMF_ERROR_SERVICE_NOT_FOUND
;
3389 case STMF_PS_ERROR_VERSION_MISMATCH
:
3390 ret
= STMF_ERROR_SERVICE_DATA_VERSION
;
3394 "stmfDeleteTargetGroup:psDeleteTargetGroup"
3396 ret
= STMF_STATUS_ERROR
;
3406 * stmfDevidFromIscsiName
3408 * Purpose: convert an iSCSI name to an stmf devid
3410 * iscsiName - unicode nul terminated utf-8 encoded iSCSI name
3411 * devid - on success, contains the converted iscsi name
3414 stmfDevidFromIscsiName(char *iscsiName
, stmfDevid
*devid
)
3416 if (devid
== NULL
|| iscsiName
== NULL
)
3417 return (STMF_ERROR_INVALID_ARG
);
3419 bzero(devid
, sizeof (stmfDevid
));
3421 /* Validate size of target */
3422 if ((devid
->identLength
= strlen(iscsiName
)) > MAX_ISCSI_NAME
||
3423 devid
->identLength
< strlen(EUI
) ||
3424 devid
->identLength
< strlen(IQN
)) {
3425 return (STMF_ERROR_INVALID_ARG
);
3428 if ((strncmp(iscsiName
, EUI
, strlen(EUI
)) != 0) &&
3429 strncmp(iscsiName
, IQN
, strlen(IQN
)) != 0) {
3430 return (STMF_ERROR_INVALID_ARG
);
3433 /* copy UTF-8 bytes to ident */
3434 bcopy(iscsiName
, devid
->ident
, devid
->identLength
);
3436 return (STMF_STATUS_SUCCESS
);
3442 * Purpose: convert a WWN to an stmf devid
3444 * wwn - 8-byte wwn identifier
3445 * devid - on success, contains the converted wwn
3448 stmfDevidFromWwn(uchar_t
*wwn
, stmfDevid
*devid
)
3450 if (wwn
== NULL
|| devid
== NULL
)
3451 return (STMF_ERROR_INVALID_ARG
);
3453 bzero(devid
, sizeof (stmfDevid
));
3455 /* Copy eui prefix */
3456 (void) bcopy(WWN
, devid
->ident
, strlen(WWN
));
3458 /* Convert to ASCII uppercase hexadecimal string */
3459 (void) snprintf((char *)&devid
->ident
[strlen(WWN
)],
3460 sizeof (devid
->ident
), "%02X%02X%02X%02X%02X%02X%02X%02X",
3461 wwn
[0], wwn
[1], wwn
[2], wwn
[3], wwn
[4], wwn
[5], wwn
[6], wwn
[7]);
3463 devid
->identLength
= strlen((char *)devid
->ident
);
3465 return (STMF_STATUS_SUCCESS
);
3471 * Purpose: Free memory allocated by this library
3473 * memory - previously allocated pointer of memory managed by library
3476 stmfFreeMemory(void *memory
)
3482 * get host group, target group list from stmf
3484 * groupType - HOST_GROUP, TARGET_GROUP
3487 groupListIoctl(stmfGroupList
**groupList
, int groupType
)
3494 stmf_iocdata_t stmfIoctl
;
3495 /* framework group list */
3496 stmf_group_name_t
*iGroupList
= NULL
;
3497 uint32_t groupListSize
;
3499 if (groupList
== NULL
) {
3500 return (STMF_ERROR_INVALID_ARG
);
3503 if (groupType
== HOST_GROUP
) {
3504 cmd
= STMF_IOCTL_GET_HG_LIST
;
3505 } else if (groupType
== TARGET_GROUP
) {
3506 cmd
= STMF_IOCTL_GET_TG_LIST
;
3508 return (STMF_ERROR_INVALID_ARG
);
3512 ret
= initializeConfig();
3513 if (ret
!= STMF_STATUS_SUCCESS
) {
3518 * Open control node for stmf
3520 if ((ret
= openStmf(OPEN_STMF
, &fd
)) != STMF_STATUS_SUCCESS
)
3524 * Allocate ioctl input buffer
3526 groupListSize
= ALLOC_GROUP
;
3527 groupListSize
= groupListSize
* (sizeof (stmf_group_name_t
));
3528 iGroupList
= (stmf_group_name_t
*)calloc(1, groupListSize
);
3529 if (iGroupList
== NULL
) {
3530 ret
= STMF_ERROR_NOMEM
;
3534 bzero(&stmfIoctl
, sizeof (stmfIoctl
));
3536 * Issue ioctl to get the group list
3538 stmfIoctl
.stmf_version
= STMF_VERSION_1
;
3539 stmfIoctl
.stmf_obuf_size
= groupListSize
;
3540 stmfIoctl
.stmf_obuf
= (uint64_t)(unsigned long)iGroupList
;
3541 ioctlRet
= ioctl(fd
, cmd
, &stmfIoctl
);
3542 if (ioctlRet
!= 0) {
3545 ret
= STMF_ERROR_BUSY
;
3549 ret
= STMF_ERROR_PERM
;
3553 "groupListIoctl:ioctl errno(%d)",
3555 ret
= STMF_STATUS_ERROR
;
3561 * Check whether input buffer was large enough
3563 if (stmfIoctl
.stmf_obuf_max_nentries
> ALLOC_GROUP
) {
3564 groupListSize
= stmfIoctl
.stmf_obuf_max_nentries
*
3565 sizeof (stmf_group_name_t
);
3566 iGroupList
= realloc(iGroupList
, groupListSize
);
3567 if (iGroupList
== NULL
) {
3568 ret
= STMF_ERROR_NOMEM
;
3571 stmfIoctl
.stmf_obuf_size
= groupListSize
;
3572 stmfIoctl
.stmf_obuf
= (uint64_t)(unsigned long)iGroupList
;
3573 ioctlRet
= ioctl(fd
, cmd
, &stmfIoctl
);
3574 if (ioctlRet
!= 0) {
3577 ret
= STMF_ERROR_BUSY
;
3581 ret
= STMF_ERROR_PERM
;
3585 "groupListIoctl:ioctl errno(%d)",
3587 ret
= STMF_STATUS_ERROR
;
3594 /* allocate and copy to caller's buffer */
3595 *groupList
= (stmfGroupList
*)calloc(1, sizeof (stmfGroupList
) +
3596 sizeof (stmfGroupName
) * stmfIoctl
.stmf_obuf_nentries
);
3597 if (*groupList
== NULL
) {
3598 ret
= STMF_ERROR_NOMEM
;
3601 (*groupList
)->cnt
= stmfIoctl
.stmf_obuf_nentries
;
3602 for (i
= 0; i
< stmfIoctl
.stmf_obuf_nentries
; i
++) {
3603 bcopy(iGroupList
[i
].name
, (*groupList
)->name
[i
],
3604 sizeof (stmfGroupName
));
3614 * get host group members, target group members from stmf
3616 * groupProps - allocated on success
3618 * groupType - HOST_GROUP, TARGET_GROUP
3621 groupMemberListIoctl(stmfGroupName
*groupName
, stmfGroupProperties
**groupProps
,
3629 stmf_iocdata_t stmfIoctl
;
3630 /* framework group list */
3631 stmf_group_name_t iGroupName
;
3632 stmf_ge_ident_t
*iGroupMembers
;
3633 uint32_t groupListSize
;
3635 if (groupName
== NULL
) {
3636 return (STMF_ERROR_INVALID_ARG
);
3639 if (groupType
== HOST_GROUP
) {
3640 cmd
= STMF_IOCTL_GET_HG_ENTRIES
;
3641 } else if (groupType
== TARGET_GROUP
) {
3642 cmd
= STMF_IOCTL_GET_TG_ENTRIES
;
3644 return (STMF_ERROR_INVALID_ARG
);
3648 ret
= initializeConfig();
3649 if (ret
!= STMF_STATUS_SUCCESS
) {
3654 * Open control node for stmf
3656 if ((ret
= openStmf(OPEN_STMF
, &fd
)) != STMF_STATUS_SUCCESS
)
3659 bzero(&iGroupName
, sizeof (iGroupName
));
3661 bcopy(groupName
, &iGroupName
.name
, strlen((char *)groupName
));
3663 iGroupName
.name_size
= strlen((char *)groupName
);
3666 * Allocate ioctl input buffer
3668 groupListSize
= ALLOC_GRP_MEMBER
;
3669 groupListSize
= groupListSize
* (sizeof (stmf_ge_ident_t
));
3670 iGroupMembers
= (stmf_ge_ident_t
*)calloc(1, groupListSize
);
3671 if (iGroupMembers
== NULL
) {
3672 ret
= STMF_ERROR_NOMEM
;
3676 bzero(&stmfIoctl
, sizeof (stmfIoctl
));
3678 * Issue ioctl to get the group list
3680 stmfIoctl
.stmf_version
= STMF_VERSION_1
;
3681 stmfIoctl
.stmf_ibuf
= (uint64_t)(unsigned long)&iGroupName
;
3682 stmfIoctl
.stmf_ibuf_size
= sizeof (stmf_group_name_t
);
3683 stmfIoctl
.stmf_obuf_size
= groupListSize
;
3684 stmfIoctl
.stmf_obuf
= (uint64_t)(unsigned long)iGroupMembers
;
3685 ioctlRet
= ioctl(fd
, cmd
, &stmfIoctl
);
3686 if (ioctlRet
!= 0) {
3689 ret
= STMF_ERROR_BUSY
;
3693 ret
= STMF_ERROR_PERM
;
3697 "groupListIoctl:ioctl errno(%d)",
3699 ret
= STMF_STATUS_ERROR
;
3705 * Check whether input buffer was large enough
3707 if (stmfIoctl
.stmf_obuf_max_nentries
> ALLOC_GRP_MEMBER
) {
3708 groupListSize
= stmfIoctl
.stmf_obuf_max_nentries
*
3709 sizeof (stmf_ge_ident_t
);
3710 iGroupMembers
= realloc(iGroupMembers
, groupListSize
);
3711 if (iGroupMembers
== NULL
) {
3712 ret
= STMF_ERROR_NOMEM
;
3715 stmfIoctl
.stmf_ibuf
= (uint64_t)(unsigned long)&iGroupName
;
3716 stmfIoctl
.stmf_ibuf_size
= sizeof (stmf_group_name_t
);
3717 stmfIoctl
.stmf_obuf_size
= groupListSize
;
3718 stmfIoctl
.stmf_obuf
= (uint64_t)(unsigned long)iGroupMembers
;
3719 ioctlRet
= ioctl(fd
, cmd
, &stmfIoctl
);
3720 if (ioctlRet
!= 0) {
3723 ret
= STMF_ERROR_BUSY
;
3727 ret
= STMF_ERROR_PERM
;
3731 "groupListIoctl:ioctl errno(%d)",
3733 ret
= STMF_STATUS_ERROR
;
3740 /* allocate and copy to caller's buffer */
3741 *groupProps
= (stmfGroupProperties
*)calloc(1,
3742 sizeof (stmfGroupProperties
) +
3743 sizeof (stmfDevid
) * stmfIoctl
.stmf_obuf_nentries
);
3744 if (*groupProps
== NULL
) {
3745 ret
= STMF_ERROR_NOMEM
;
3748 (*groupProps
)->cnt
= stmfIoctl
.stmf_obuf_nentries
;
3749 for (i
= 0; i
< stmfIoctl
.stmf_obuf_nentries
; i
++) {
3750 (*groupProps
)->name
[i
].identLength
=
3751 iGroupMembers
[i
].ident_size
;
3752 bcopy(iGroupMembers
[i
].ident
, (*groupProps
)->name
[i
].ident
,
3753 iGroupMembers
[i
].ident_size
);
3757 free(iGroupMembers
);
3763 * Purpose: access persistent config data for host groups and target groups
3766 iLoadGroupFromPs(stmfGroupList
**groupList
, int type
)
3770 if (groupList
== NULL
) {
3771 return (STMF_ERROR_INVALID_ARG
);
3774 if (type
== HOST_GROUP
) {
3775 ret
= psGetHostGroupList(groupList
);
3776 } else if (type
== TARGET_GROUP
) {
3777 ret
= psGetTargetGroupList(groupList
);
3779 return (STMF_ERROR_INVALID_ARG
);
3782 case STMF_PS_SUCCESS
:
3783 ret
= STMF_STATUS_SUCCESS
;
3785 case STMF_PS_ERROR_NOT_FOUND
:
3786 ret
= STMF_ERROR_NOT_FOUND
;
3788 case STMF_PS_ERROR_BUSY
:
3789 ret
= STMF_ERROR_BUSY
;
3791 case STMF_PS_ERROR_SERVICE_NOT_FOUND
:
3792 ret
= STMF_ERROR_SERVICE_NOT_FOUND
;
3794 case STMF_PS_ERROR_VERSION_MISMATCH
:
3795 ret
= STMF_ERROR_SERVICE_DATA_VERSION
;
3799 "stmfGetHostGroupList:psGetHostGroupList:error(%d)",
3801 ret
= STMF_STATUS_ERROR
;
3809 * stmfGetHostGroupList
3811 * Purpose: Retrieves the list of initiator group oids
3813 * hostGroupList - pointer to pointer to hostGroupList structure
3814 * on success, this contains the host group list.
3817 stmfGetHostGroupList(stmfGroupList
**hostGroupList
)
3819 int ret
= STMF_STATUS_ERROR
;
3821 if (hostGroupList
== NULL
) {
3822 return (STMF_ERROR_INVALID_ARG
);
3825 ret
= groupListIoctl(hostGroupList
, HOST_GROUP
);
3831 * Purpose: access persistent config data for host groups and target groups
3834 iLoadGroupMembersFromPs(stmfGroupName
*groupName
,
3835 stmfGroupProperties
**groupProp
, int type
)
3839 if (groupName
== NULL
) {
3840 return (STMF_ERROR_INVALID_ARG
);
3843 if (type
== HOST_GROUP
) {
3844 ret
= psGetHostGroupMemberList((char *)groupName
, groupProp
);
3845 } else if (type
== TARGET_GROUP
) {
3846 ret
= psGetTargetGroupMemberList((char *)groupName
, groupProp
);
3848 return (STMF_ERROR_INVALID_ARG
);
3851 case STMF_PS_SUCCESS
:
3852 ret
= STMF_STATUS_SUCCESS
;
3854 case STMF_PS_ERROR_NOT_FOUND
:
3855 ret
= STMF_ERROR_NOT_FOUND
;
3857 case STMF_PS_ERROR_BUSY
:
3858 ret
= STMF_ERROR_BUSY
;
3860 case STMF_PS_ERROR_SERVICE_NOT_FOUND
:
3861 ret
= STMF_ERROR_SERVICE_NOT_FOUND
;
3863 case STMF_PS_ERROR_VERSION_MISMATCH
:
3864 ret
= STMF_ERROR_SERVICE_DATA_VERSION
;
3868 "iLoadGroupMembersFromPs:psGetHostGroupList:"
3870 ret
= STMF_STATUS_ERROR
;
3878 * stmfGetHostGroupMembers
3880 * Purpose: Retrieves the group properties for a host group
3882 * groupName - name of group for which to retrieve host group members.
3883 * groupProp - pointer to pointer to stmfGroupProperties structure
3884 * on success, this contains the list of group members.
3887 stmfGetHostGroupMembers(stmfGroupName
*groupName
,
3888 stmfGroupProperties
**groupProp
)
3892 if (groupName
== NULL
|| groupProp
== NULL
) {
3893 return (STMF_ERROR_INVALID_ARG
);
3896 ret
= groupMemberListIoctl(groupName
, groupProp
, HOST_GROUP
);
3902 * stmfGetProviderData
3904 * Purpose: Get provider data list
3906 * providerName - name of provider for which to retrieve the data
3907 * nvl - pointer to nvlist_t pointer which will contain the nvlist data
3909 * providerType - type of provider for which to retrieve data.
3910 * STMF_LU_PROVIDER_TYPE
3911 * STMF_PORT_PROVIDER_TYPE
3914 stmfGetProviderData(char *providerName
, nvlist_t
**nvl
, int providerType
)
3916 return (stmfGetProviderDataProt(providerName
, nvl
, providerType
,
3921 * stmfGetProviderDataProt
3923 * Purpose: Get provider data list with token
3925 * providerName - name of provider for which to retrieve the data
3926 * nvl - pointer to nvlist_t pointer which will contain the nvlist data
3928 * providerType - type of provider for which to retrieve data.
3929 * STMF_LU_PROVIDER_TYPE
3930 * STMF_PORT_PROVIDER_TYPE
3931 * setToken - Returns the stale data token
3934 stmfGetProviderDataProt(char *providerName
, nvlist_t
**nvl
, int providerType
,
3939 if (providerName
== NULL
|| nvl
== NULL
) {
3940 return (STMF_ERROR_INVALID_ARG
);
3942 if (providerType
!= STMF_LU_PROVIDER_TYPE
&&
3943 providerType
!= STMF_PORT_PROVIDER_TYPE
) {
3944 return (STMF_ERROR_INVALID_ARG
);
3947 ret
= initializeConfig();
3948 if (ret
!= STMF_STATUS_SUCCESS
) {
3951 return (getProviderData(providerName
, nvl
, providerType
, setToken
));
3955 * stmfGetProviderDataList
3957 * Purpose: Get the list of providers currently persisting data
3959 * providerList - pointer to pointer to an stmfProviderList structure allocated
3960 * by the caller. Will contain the list of providers on success.
3963 stmfGetProviderDataList(stmfProviderList
**providerList
)
3967 ret
= psGetProviderDataList(providerList
);
3969 case STMF_PS_SUCCESS
:
3970 ret
= STMF_STATUS_SUCCESS
;
3972 case STMF_PS_ERROR_BUSY
:
3973 ret
= STMF_ERROR_BUSY
;
3975 case STMF_PS_ERROR_SERVICE_NOT_FOUND
:
3976 ret
= STMF_ERROR_SERVICE_NOT_FOUND
;
3978 case STMF_PS_ERROR_VERSION_MISMATCH
:
3979 ret
= STMF_ERROR_SERVICE_DATA_VERSION
;
3983 "stmfGetProviderDataList:psGetProviderDataList"
3985 ret
= STMF_STATUS_ERROR
;
3994 * stmfGetSessionList
3996 * Purpose: Retrieves the session list for a target (devid)
3998 * devid - devid of target for which to retrieve session information.
3999 * sessionList - pointer to pointer to stmfSessionList structure
4000 * on success, this contains the list of initiator sessions.
4003 stmfGetSessionList(stmfDevid
*devid
, stmfSessionList
**sessionList
)
4005 int ret
= STMF_STATUS_SUCCESS
;
4008 int cmd
= STMF_IOCTL_SESSION_LIST
;
4010 stmf_iocdata_t stmfIoctl
;
4011 slist_scsi_session_t
*fSessionList
, *fSessionListP
= NULL
;
4013 uint32_t fSessionListSize
;
4015 if (sessionList
== NULL
|| devid
== NULL
) {
4016 ret
= STMF_ERROR_INVALID_ARG
;
4020 ret
= initializeConfig();
4021 if (ret
!= STMF_STATUS_SUCCESS
) {
4026 * Open control node for stmf
4028 if ((ret
= openStmf(OPEN_STMF
, &fd
)) != STMF_STATUS_SUCCESS
)
4032 * Allocate ioctl input buffer
4034 fSessionListSize
= ALLOC_SESSION
;
4035 fSessionListSize
= fSessionListSize
* (sizeof (slist_scsi_session_t
));
4036 fSessionList
= (slist_scsi_session_t
*)calloc(1, fSessionListSize
);
4037 fSessionListP
= fSessionList
;
4038 if (fSessionList
== NULL
) {
4039 ret
= STMF_ERROR_NOMEM
;
4043 ident
[IDENT_LENGTH_BYTE
] = devid
->identLength
;
4044 bcopy(&(devid
->ident
), &ident
[IDENT_LENGTH_BYTE
+ 1],
4045 devid
->identLength
);
4047 bzero(&stmfIoctl
, sizeof (stmfIoctl
));
4049 * Issue ioctl to get the session list
4051 stmfIoctl
.stmf_version
= STMF_VERSION_1
;
4052 stmfIoctl
.stmf_ibuf
= (uint64_t)(unsigned long)&ident
;
4053 stmfIoctl
.stmf_ibuf_size
= sizeof (ident
);
4054 stmfIoctl
.stmf_obuf_size
= fSessionListSize
;
4055 stmfIoctl
.stmf_obuf
= (uint64_t)(unsigned long)fSessionList
;
4056 ioctlRet
= ioctl(fd
, cmd
, &stmfIoctl
);
4057 if (ioctlRet
!= 0) {
4060 ret
= STMF_ERROR_BUSY
;
4064 ret
= STMF_ERROR_PERM
;
4068 "stmfGetSessionList:ioctl errno(%d)",
4070 ret
= STMF_STATUS_ERROR
;
4076 * Check whether input buffer was large enough
4078 if (stmfIoctl
.stmf_obuf_max_nentries
> ALLOC_SESSION
) {
4079 fSessionListSize
= stmfIoctl
.stmf_obuf_max_nentries
*
4080 sizeof (slist_scsi_session_t
);
4081 fSessionList
= realloc(fSessionList
, fSessionListSize
);
4082 if (fSessionList
== NULL
) {
4083 ret
= STMF_ERROR_NOMEM
;
4086 fSessionListP
= fSessionList
;
4087 stmfIoctl
.stmf_obuf_size
= fSessionListSize
;
4088 stmfIoctl
.stmf_obuf
= (uint64_t)(unsigned long)fSessionList
;
4089 ioctlRet
= ioctl(fd
, cmd
, &stmfIoctl
);
4090 if (ioctlRet
!= 0) {
4093 ret
= STMF_ERROR_BUSY
;
4097 ret
= STMF_ERROR_PERM
;
4101 "stmfGetSessionList:ioctl "
4102 "errno(%d)", errno
);
4103 ret
= STMF_STATUS_ERROR
;
4111 * allocate caller's buffer with the final size
4113 *sessionList
= (stmfSessionList
*)calloc(1, sizeof (stmfSessionList
) +
4114 stmfIoctl
.stmf_obuf_max_nentries
* sizeof (stmfSession
));
4115 if (*sessionList
== NULL
) {
4116 ret
= STMF_ERROR_NOMEM
;
4121 (*sessionList
)->cnt
= stmfIoctl
.stmf_obuf_max_nentries
;
4124 * copy session info to caller's buffer
4126 for (i
= 0; i
< (*sessionList
)->cnt
; i
++) {
4127 (*sessionList
)->session
[i
].initiator
.identLength
=
4128 fSessionList
->initiator
[IDENT_LENGTH_BYTE
];
4129 bcopy(&(fSessionList
->initiator
[IDENT_LENGTH_BYTE
+ 1]),
4130 (*sessionList
)->session
[i
].initiator
.ident
,
4132 bcopy(&(fSessionList
->alias
),
4133 &((*sessionList
)->session
[i
].alias
),
4134 sizeof ((*sessionList
)->session
[i
].alias
));
4135 bcopy(&(fSessionList
++->creation_time
),
4136 &((*sessionList
)->session
[i
].creationTime
),
4141 free(fSessionListP
);
4146 * stmfGetTargetGroupList
4148 * Purpose: Retrieves the list of target groups
4150 * targetGroupList - pointer to a pointer to an stmfGroupList structure. On
4151 * success, it contains the list of target groups.
4154 stmfGetTargetGroupList(stmfGroupList
**targetGroupList
)
4158 if (targetGroupList
== NULL
) {
4159 return (STMF_ERROR_INVALID_ARG
);
4162 ret
= groupListIoctl(targetGroupList
, TARGET_GROUP
);
4167 * stmfGetTargetGroupMembers
4169 * Purpose: Retrieves the group members for a target group
4171 * groupName - name of target group for which to retrieve members.
4172 * groupProp - pointer to pointer to stmfGroupProperties structure
4173 * on success, this contains the list of group members.
4176 stmfGetTargetGroupMembers(stmfGroupName
*groupName
,
4177 stmfGroupProperties
**groupProp
)
4181 if (groupName
== NULL
|| groupProp
== NULL
) {
4182 return (STMF_ERROR_INVALID_ARG
);
4185 ret
= groupMemberListIoctl(groupName
, groupProp
, TARGET_GROUP
);
4193 * Purpose: Retrieves the list of target ports
4195 * targetList - pointer to a pointer to an stmfDevidList structure.
4196 * On success, it contains the list of local ports (target).
4199 stmfGetTargetList(stmfDevidList
**targetList
)
4205 stmf_iocdata_t stmfIoctl
;
4206 /* framework target port list */
4207 slist_target_port_t
*fTargetList
, *fTargetListP
= NULL
;
4208 uint32_t fTargetListSize
;
4210 if (targetList
== NULL
) {
4211 return (STMF_ERROR_INVALID_ARG
);
4215 ret
= initializeConfig();
4216 if (ret
!= STMF_STATUS_SUCCESS
) {
4221 * Open control node for stmf
4223 if ((ret
= openStmf(OPEN_STMF
, &fd
)) != STMF_STATUS_SUCCESS
)
4227 * Allocate ioctl input buffer
4229 fTargetListSize
= ALLOC_TARGET_PORT
* sizeof (slist_target_port_t
);
4230 fTargetListP
= fTargetList
=
4231 (slist_target_port_t
*)calloc(1, fTargetListSize
);
4232 if (fTargetList
== NULL
) {
4233 ret
= STMF_ERROR_NOMEM
;
4237 bzero(&stmfIoctl
, sizeof (stmfIoctl
));
4239 * Issue ioctl to retrieve target list
4241 stmfIoctl
.stmf_version
= STMF_VERSION_1
;
4242 stmfIoctl
.stmf_obuf_size
= fTargetListSize
;
4243 stmfIoctl
.stmf_obuf
= (uint64_t)(unsigned long)fTargetList
;
4244 ioctlRet
= ioctl(fd
, STMF_IOCTL_TARGET_PORT_LIST
, &stmfIoctl
);
4245 if (ioctlRet
!= 0) {
4248 ret
= STMF_ERROR_BUSY
;
4252 ret
= STMF_ERROR_PERM
;
4256 "stmfGetTargetList:ioctl errno(%d)", errno
);
4257 ret
= STMF_STATUS_ERROR
;
4263 * Check whether input buffer was large enough
4265 if (stmfIoctl
.stmf_obuf_max_nentries
> ALLOC_TARGET_PORT
) {
4266 fTargetListSize
= stmfIoctl
.stmf_obuf_max_nentries
*
4267 sizeof (slist_target_port_t
);
4268 fTargetListP
= fTargetList
=
4269 realloc(fTargetList
, fTargetListSize
);
4270 if (fTargetList
== NULL
) {
4271 ret
= STMF_ERROR_NOMEM
;
4274 stmfIoctl
.stmf_obuf_size
= fTargetListSize
;
4275 stmfIoctl
.stmf_obuf
= (uint64_t)(unsigned long)fTargetList
;
4276 ioctlRet
= ioctl(fd
, STMF_IOCTL_TARGET_PORT_LIST
,
4278 if (ioctlRet
!= 0) {
4281 ret
= STMF_ERROR_BUSY
;
4285 ret
= STMF_ERROR_PERM
;
4289 "stmfGetTargetList:ioctl errno(%d)",
4291 ret
= STMF_STATUS_ERROR
;
4298 *targetList
= (stmfDevidList
*)calloc(1,
4299 stmfIoctl
.stmf_obuf_max_nentries
* sizeof (stmfDevid
) +
4300 sizeof (stmfDevidList
));
4301 if (*targetList
== NULL
) {
4302 ret
= STMF_ERROR_NOMEM
;
4306 (*targetList
)->cnt
= stmfIoctl
.stmf_obuf_max_nentries
;
4307 for (i
= 0; i
< stmfIoctl
.stmf_obuf_max_nentries
; i
++, fTargetList
++) {
4308 (*targetList
)->devid
[i
].identLength
=
4309 fTargetList
->target
[IDENT_LENGTH_BYTE
];
4310 bcopy(&fTargetList
->target
[IDENT_LENGTH_BYTE
+ 1],
4311 &(*targetList
)->devid
[i
].ident
,
4312 fTargetList
->target
[IDENT_LENGTH_BYTE
]);
4322 * stmfGetTargetProperties
4324 * Purpose: Retrieves the properties for a logical unit
4326 * devid - devid of the target for which to retrieve properties
4327 * targetProps - pointer to an stmfTargetProperties structure.
4328 * On success, it contains the target properties for
4329 * the specified devid.
4332 stmfGetTargetProperties(stmfDevid
*devid
, stmfTargetProperties
*targetProps
)
4334 int ret
= STMF_STATUS_SUCCESS
;
4337 stmf_iocdata_t stmfIoctl
;
4338 sioc_target_port_props_t targetProperties
;
4339 scsi_devid_desc_t
*scsiDevid
;
4341 if (devid
== NULL
|| targetProps
== NULL
) {
4342 return (STMF_ERROR_INVALID_ARG
);
4346 ret
= initializeConfig();
4347 if (ret
!= STMF_STATUS_SUCCESS
) {
4352 * Open control node for stmf
4354 if ((ret
= openStmf(OPEN_STMF
, &fd
)) != STMF_STATUS_SUCCESS
)
4357 targetProperties
.tgt_id
[IDENT_LENGTH_BYTE
] = devid
->identLength
;
4358 bcopy(&(devid
->ident
), &targetProperties
.tgt_id
[IDENT_LENGTH_BYTE
+ 1],
4359 devid
->identLength
);
4361 bzero(&stmfIoctl
, sizeof (stmfIoctl
));
4363 * Issue ioctl to add to the host group
4365 stmfIoctl
.stmf_version
= STMF_VERSION_1
;
4366 stmfIoctl
.stmf_ibuf_size
= sizeof (targetProperties
.tgt_id
);
4367 stmfIoctl
.stmf_ibuf
= (uint64_t)(unsigned long)&targetProperties
.tgt_id
;
4368 stmfIoctl
.stmf_obuf
= (uint64_t)(unsigned long)&targetProperties
;
4369 stmfIoctl
.stmf_obuf_size
= sizeof (targetProperties
);
4370 ioctlRet
= ioctl(fd
, STMF_IOCTL_GET_TARGET_PORT_PROPERTIES
,
4372 if (ioctlRet
!= 0) {
4375 ret
= STMF_ERROR_BUSY
;
4379 ret
= STMF_ERROR_PERM
;
4382 ret
= STMF_ERROR_NOT_FOUND
;
4386 "stmfGetTargetProperties:ioctl errno(%d)",
4388 ret
= STMF_STATUS_ERROR
;
4394 bcopy(targetProperties
.tgt_provider_name
, targetProps
->providerName
,
4395 sizeof (targetProperties
.tgt_provider_name
));
4396 if (targetProperties
.tgt_state
== STMF_STATE_ONLINE
) {
4397 targetProps
->status
= STMF_TARGET_PORT_ONLINE
;
4398 } else if (targetProperties
.tgt_state
== STMF_STATE_OFFLINE
) {
4399 targetProps
->status
= STMF_TARGET_PORT_OFFLINE
;
4400 } else if (targetProperties
.tgt_state
== STMF_STATE_ONLINING
) {
4401 targetProps
->status
= STMF_TARGET_PORT_ONLINING
;
4402 } else if (targetProperties
.tgt_state
== STMF_STATE_OFFLINING
) {
4403 targetProps
->status
= STMF_TARGET_PORT_OFFLINING
;
4405 bcopy(targetProperties
.tgt_alias
, targetProps
->alias
,
4406 sizeof (targetProps
->alias
));
4408 scsiDevid
= (scsi_devid_desc_t
*)&targetProperties
.tgt_id
;
4409 targetProps
->protocol
= scsiDevid
->protocol_id
;
4417 * stmfGetLogicalUnitList
4419 * Purpose: Retrieves list of logical unit Object IDs
4421 * luList - pointer to a pointer to a stmfGuidList structure. On success,
4422 * it contains the list of logical unit guids.
4426 stmfGetLogicalUnitList(stmfGuidList
**luList
)
4431 int cmd
= STMF_IOCTL_LU_LIST
;
4433 stmf_iocdata_t stmfIoctl
;
4434 slist_lu_t
*fLuList
;
4435 uint32_t fLuListSize
;
4438 if (luList
== NULL
) {
4439 return (STMF_ERROR_INVALID_ARG
);
4443 ret
= initializeConfig();
4444 if (ret
!= STMF_STATUS_SUCCESS
) {
4449 * Open control node for stmf
4451 if ((ret
= openStmf(OPEN_STMF
, &fd
)) != STMF_STATUS_SUCCESS
)
4455 * Allocate ioctl input buffer
4457 fLuListSize
= ALLOC_LU
;
4458 fLuListSize
= fLuListSize
* (sizeof (slist_lu_t
));
4459 fLuList
= (slist_lu_t
*)calloc(1, fLuListSize
);
4460 if (fLuList
== NULL
) {
4461 ret
= STMF_ERROR_NOMEM
;
4465 bzero(&stmfIoctl
, sizeof (stmfIoctl
));
4467 * Issue ioctl to get the LU list
4469 stmfIoctl
.stmf_version
= STMF_VERSION_1
;
4470 stmfIoctl
.stmf_obuf_size
= fLuListSize
;
4471 stmfIoctl
.stmf_obuf
= (uint64_t)(unsigned long)fLuList
;
4472 ioctlRet
= ioctl(fd
, cmd
, &stmfIoctl
);
4473 if (ioctlRet
!= 0) {
4476 ret
= STMF_ERROR_BUSY
;
4480 ret
= STMF_ERROR_PERM
;
4484 "stmfGetLogicalUnitList:ioctl errno(%d)",
4486 ret
= STMF_STATUS_ERROR
;
4492 * Check whether input buffer was large enough
4494 if (stmfIoctl
.stmf_obuf_max_nentries
> ALLOC_LU
) {
4495 fLuListSize
= stmfIoctl
.stmf_obuf_max_nentries
*
4496 sizeof (slist_lu_t
);
4498 fLuList
= (slist_lu_t
*)calloc(1, fLuListSize
);
4499 if (fLuList
== NULL
) {
4500 ret
= STMF_ERROR_NOMEM
;
4503 stmfIoctl
.stmf_obuf_size
= fLuListSize
;
4504 stmfIoctl
.stmf_obuf
= (uint64_t)(unsigned long)fLuList
;
4505 ioctlRet
= ioctl(fd
, cmd
, &stmfIoctl
);
4506 if (ioctlRet
!= 0) {
4509 ret
= STMF_ERROR_BUSY
;
4513 ret
= STMF_ERROR_PERM
;
4517 "stmfGetLogicalUnitList:"
4518 "ioctl errno(%d)", errno
);
4519 ret
= STMF_STATUS_ERROR
;
4526 if (ret
!= STMF_STATUS_SUCCESS
) {
4530 listCnt
= stmfIoctl
.stmf_obuf_nentries
;
4533 * allocate caller's buffer with the final size
4535 *luList
= (stmfGuidList
*)calloc(1, sizeof (stmfGuidList
) +
4536 listCnt
* sizeof (stmfGuid
));
4537 if (*luList
== NULL
) {
4538 ret
= STMF_ERROR_NOMEM
;
4542 (*luList
)->cnt
= listCnt
;
4544 /* copy to caller's buffer */
4545 for (i
= 0; i
< listCnt
; i
++) {
4546 bcopy(&fLuList
[i
].lu_guid
, (*luList
)->guid
[i
].guid
,
4551 * sort the list. This gives a consistent view across gets
4553 qsort((void *)&((*luList
)->guid
[0]), (*luList
)->cnt
,
4554 sizeof (stmfGuid
), guidCompare
);
4559 * free internal buffers
4566 * stmfGetLogicalUnitProperties
4568 * Purpose: Retrieves the properties for a logical unit
4570 * lu - guid of the logical unit for which to retrieve properties
4571 * stmfLuProps - pointer to an stmfLogicalUnitProperties structure. On success,
4572 * it contains the logical unit properties for the specified guid.
4575 stmfGetLogicalUnitProperties(stmfGuid
*lu
, stmfLogicalUnitProperties
*luProps
)
4577 int ret
= STMF_STATUS_SUCCESS
;
4581 int cmd
= STMF_IOCTL_GET_LU_PROPERTIES
;
4582 stmfViewEntryList
*viewEntryList
= NULL
;
4583 stmf_iocdata_t stmfIoctl
;
4584 sioc_lu_props_t fLuProps
;
4586 if (lu
== NULL
|| luProps
== NULL
) {
4587 return (STMF_ERROR_INVALID_ARG
);
4590 bzero(luProps
, sizeof (stmfLogicalUnitProperties
));
4593 ret
= initializeConfig();
4594 if (ret
!= STMF_STATUS_SUCCESS
) {
4599 * Open control node for stmf
4601 if ((ret
= openStmf(OPEN_STMF
, &fd
)) != STMF_STATUS_SUCCESS
)
4604 bzero(&stmfIoctl
, sizeof (stmfIoctl
));
4606 * Issue ioctl to add to the host group
4608 stmfIoctl
.stmf_version
= STMF_VERSION_1
;
4609 stmfIoctl
.stmf_ibuf_size
= sizeof (stmfGuid
);
4610 stmfIoctl
.stmf_ibuf
= (uint64_t)(unsigned long)lu
;
4611 stmfIoctl
.stmf_obuf
= (uint64_t)(unsigned long)&fLuProps
;
4612 stmfIoctl
.stmf_obuf_size
= sizeof (fLuProps
);
4613 ioctlRet
= ioctl(fd
, cmd
, &stmfIoctl
);
4614 if (ioctlRet
!= 0) {
4617 ret
= STMF_ERROR_BUSY
;
4621 ret
= STMF_ERROR_PERM
;
4624 stmfRet
= stmfGetViewEntryList(lu
,
4626 if (stmfRet
== STMF_STATUS_SUCCESS
) {
4628 STMF_LOGICAL_UNIT_UNREGISTERED
;
4629 if (viewEntryList
->cnt
> 0) {
4630 ret
= STMF_STATUS_SUCCESS
;
4632 ret
= STMF_ERROR_NOT_FOUND
;
4635 ret
= STMF_ERROR_NOT_FOUND
;
4637 stmfFreeMemory(viewEntryList
);
4641 "stmfGetLogicalUnit:ioctl errno(%d)",
4643 ret
= STMF_STATUS_ERROR
;
4649 bcopy(fLuProps
.lu_provider_name
, luProps
->providerName
,
4650 sizeof (fLuProps
.lu_provider_name
));
4651 if (fLuProps
.lu_state
== STMF_STATE_ONLINE
) {
4652 luProps
->status
= STMF_LOGICAL_UNIT_ONLINE
;
4653 } else if (fLuProps
.lu_state
== STMF_STATE_OFFLINE
) {
4654 luProps
->status
= STMF_LOGICAL_UNIT_OFFLINE
;
4655 } else if (fLuProps
.lu_state
== STMF_STATE_ONLINING
) {
4656 luProps
->status
= STMF_LOGICAL_UNIT_ONLINING
;
4657 } else if (fLuProps
.lu_state
== STMF_STATE_OFFLINING
) {
4658 luProps
->status
= STMF_LOGICAL_UNIT_OFFLINING
;
4660 bcopy(fLuProps
.lu_alias
, luProps
->alias
, sizeof (luProps
->alias
));
4669 * Purpose: retrieve the current state of the stmf module
4671 * state - pointer to stmfState structure allocated by the caller
4672 * On success, contains the state of stmf
4675 stmfGetState(stmfState
*state
)
4678 stmf_state_desc_t iState
;
4680 if (state
== NULL
) {
4681 return (STMF_ERROR_INVALID_ARG
);
4684 ret
= getStmfState(&iState
);
4685 if (ret
!= STMF_STATUS_SUCCESS
) {
4688 switch (iState
.state
) {
4689 case STMF_STATE_ONLINE
:
4690 state
->operationalState
=
4691 STMF_SERVICE_STATE_ONLINE
;
4693 case STMF_STATE_OFFLINE
:
4694 state
->operationalState
=
4695 STMF_SERVICE_STATE_OFFLINE
;
4697 case STMF_STATE_ONLINING
:
4698 state
->operationalState
=
4699 STMF_SERVICE_STATE_ONLINING
;
4701 case STMF_STATE_OFFLINING
:
4702 state
->operationalState
=
4703 STMF_SERVICE_STATE_OFFLINING
;
4706 state
->operationalState
=
4707 STMF_SERVICE_STATE_UNKNOWN
;
4710 switch (iState
.config_state
) {
4711 case STMF_CONFIG_NONE
:
4712 state
->configState
= STMF_CONFIG_STATE_NONE
;
4714 case STMF_CONFIG_INIT
:
4715 state
->configState
= STMF_CONFIG_STATE_INIT
;
4717 case STMF_CONFIG_INIT_DONE
:
4718 state
->configState
=
4719 STMF_CONFIG_STATE_INIT_DONE
;
4722 state
->configState
=
4723 STMF_CONFIG_STATE_UNKNOWN
;
4726 return (STMF_STATUS_SUCCESS
);
4730 * stmfGetViewEntryList
4732 * Purpose: Retrieves the list of view entries for the specified
4735 * lu - the guid of the logical unit for which to retrieve the view entry list
4736 * viewEntryList - a pointer to a pointer to a stmfViewEntryList structure. On
4737 * success, contains the list of view entries.
4740 stmfGetViewEntryList(stmfGuid
*lu
, stmfViewEntryList
**viewEntryList
)
4745 int cmd
= STMF_IOCTL_LU_VE_LIST
;
4747 stmf_iocdata_t stmfIoctl
;
4748 stmf_view_op_entry_t
*fVeList
;
4749 uint32_t fVeListSize
;
4752 if (lu
== NULL
|| viewEntryList
== NULL
) {
4753 return (STMF_ERROR_INVALID_ARG
);
4757 ret
= initializeConfig();
4758 if (ret
!= STMF_STATUS_SUCCESS
) {
4763 * Open control node for stmf
4765 if ((ret
= openStmf(OPEN_STMF
, &fd
)) != STMF_STATUS_SUCCESS
)
4769 * Allocate ioctl input buffer
4771 fVeListSize
= ALLOC_VE
;
4772 fVeListSize
= fVeListSize
* (sizeof (stmf_view_op_entry_t
));
4773 fVeList
= (stmf_view_op_entry_t
*)calloc(1, fVeListSize
);
4774 if (fVeList
== NULL
) {
4775 ret
= STMF_ERROR_NOMEM
;
4779 bzero(&stmfIoctl
, sizeof (stmfIoctl
));
4781 * Issue ioctl to get the LU list
4783 stmfIoctl
.stmf_version
= STMF_VERSION_1
;
4784 stmfIoctl
.stmf_ibuf
= (uint64_t)(unsigned long)lu
;
4785 stmfIoctl
.stmf_ibuf_size
= sizeof (stmfGuid
);
4786 stmfIoctl
.stmf_obuf_size
= fVeListSize
;
4787 stmfIoctl
.stmf_obuf
= (uint64_t)(unsigned long)fVeList
;
4788 ioctlRet
= ioctl(fd
, cmd
, &stmfIoctl
);
4789 if (ioctlRet
!= 0) {
4792 ret
= STMF_ERROR_BUSY
;
4796 ret
= STMF_ERROR_PERM
;
4800 "stmfGetViewEntryList:ioctl errno(%d)",
4802 ret
= STMF_STATUS_ERROR
;
4808 * Check whether input buffer was large enough
4810 if (stmfIoctl
.stmf_obuf_max_nentries
> ALLOC_VE
) {
4811 bzero(&stmfIoctl
, sizeof (stmfIoctl
));
4812 fVeListSize
= stmfIoctl
.stmf_obuf_max_nentries
*
4813 sizeof (stmf_view_op_entry_t
);
4815 fVeList
= (stmf_view_op_entry_t
*)calloc(1, fVeListSize
);
4816 if (fVeList
== NULL
) {
4817 return (STMF_ERROR_NOMEM
);
4819 stmfIoctl
.stmf_obuf_size
= fVeListSize
;
4820 stmfIoctl
.stmf_obuf
= (uint64_t)(unsigned long)fVeList
;
4821 ioctlRet
= ioctl(fd
, cmd
, &stmfIoctl
);
4822 if (ioctlRet
!= 0) {
4825 ret
= STMF_ERROR_BUSY
;
4829 ret
= STMF_ERROR_PERM
;
4833 "stmfGetLogicalUnitList:"
4834 "ioctl errno(%d)", errno
);
4835 ret
= STMF_STATUS_ERROR
;
4842 if (ret
!= STMF_STATUS_SUCCESS
) {
4846 listCnt
= stmfIoctl
.stmf_obuf_nentries
;
4849 * allocate caller's buffer with the final size
4851 *viewEntryList
= (stmfViewEntryList
*)calloc(1,
4852 sizeof (stmfViewEntryList
) + listCnt
* sizeof (stmfViewEntry
));
4853 if (*viewEntryList
== NULL
) {
4854 ret
= STMF_ERROR_NOMEM
;
4858 (*viewEntryList
)->cnt
= listCnt
;
4860 /* copy to caller's buffer */
4861 for (i
= 0; i
< listCnt
; i
++) {
4862 (*viewEntryList
)->ve
[i
].veIndexValid
= B_TRUE
;
4863 (*viewEntryList
)->ve
[i
].veIndex
= fVeList
[i
].ve_ndx
;
4864 if (fVeList
[i
].ve_all_hosts
== 1) {
4865 (*viewEntryList
)->ve
[i
].allHosts
= B_TRUE
;
4867 bcopy(fVeList
[i
].ve_host_group
.name
,
4868 (*viewEntryList
)->ve
[i
].hostGroup
,
4869 fVeList
[i
].ve_host_group
.name_size
);
4871 if (fVeList
[i
].ve_all_targets
== 1) {
4872 (*viewEntryList
)->ve
[i
].allTargets
= B_TRUE
;
4874 bcopy(fVeList
[i
].ve_target_group
.name
,
4875 (*viewEntryList
)->ve
[i
].targetGroup
,
4876 fVeList
[i
].ve_target_group
.name_size
);
4878 bcopy(fVeList
[i
].ve_lu_nbr
, (*viewEntryList
)->ve
[i
].luNbr
,
4879 sizeof ((*viewEntryList
)->ve
[i
].luNbr
));
4880 (*viewEntryList
)->ve
[i
].luNbrValid
= B_TRUE
;
4884 * sort the list. This gives a consistent view across gets
4886 qsort((void *)&((*viewEntryList
)->ve
[0]), (*viewEntryList
)->cnt
,
4887 sizeof (stmfViewEntry
), viewEntryCompare
);
4892 * free internal buffers
4902 * Purpose - issues the ioctl to load the host groups into stmf
4904 * fd - file descriptor for the control node of stmf.
4905 * groupList - populated host group list
4908 loadHostGroups(int fd
, stmfGroupList
*groupList
)
4911 int ret
= STMF_STATUS_SUCCESS
;
4912 stmfGroupProperties
*groupProps
= NULL
;
4914 for (i
= 0; i
< groupList
->cnt
; i
++) {
4915 if ((ret
= groupIoctl(fd
, STMF_IOCTL_CREATE_HOST_GROUP
,
4916 &(groupList
->name
[i
]))) != STMF_STATUS_SUCCESS
) {
4919 ret
= iLoadGroupMembersFromPs(&(groupList
->name
[i
]),
4920 &groupProps
, HOST_GROUP
);
4921 for (j
= 0; j
< groupProps
->cnt
; j
++) {
4922 if ((ret
= groupMemberIoctl(fd
, STMF_IOCTL_ADD_HG_ENTRY
,
4923 &(groupList
->name
[i
]), &(groupProps
->name
[j
])))
4924 != STMF_STATUS_SUCCESS
) {
4932 stmfFreeMemory(groupProps
);
4939 * Purpose - issues the ioctl to load the target groups into stmf
4941 * fd - file descriptor for the control node of stmf.
4942 * groupList - populated target group list.
4945 loadTargetGroups(int fd
, stmfGroupList
*groupList
)
4948 int ret
= STMF_STATUS_SUCCESS
;
4949 stmfGroupProperties
*groupProps
= NULL
;
4951 for (i
= 0; i
< groupList
->cnt
; i
++) {
4952 if ((ret
= groupIoctl(fd
, STMF_IOCTL_CREATE_TARGET_GROUP
,
4953 &(groupList
->name
[i
]))) != STMF_STATUS_SUCCESS
) {
4956 ret
= iLoadGroupMembersFromPs(&(groupList
->name
[i
]),
4957 &groupProps
, TARGET_GROUP
);
4958 for (j
= 0; j
< groupProps
->cnt
; j
++) {
4959 if ((ret
= groupMemberIoctl(fd
, STMF_IOCTL_ADD_TG_ENTRY
,
4960 &(groupList
->name
[i
]), &(groupProps
->name
[j
])))
4961 != STMF_STATUS_SUCCESS
) {
4969 stmfFreeMemory(groupProps
);
4977 * Purpose: Load the configuration data from the store
4979 * First load the host groups and target groups, then the view entries
4980 * and finally the provider data
4982 * fd - file descriptor of control node for stmf.
4989 stmfGroupList
*groupList
= NULL
;
4990 stmfGuidList
*guidList
= NULL
;
4991 stmfViewEntryList
*viewEntryList
= NULL
;
4992 stmfProviderList
*providerList
= NULL
;
4994 nvlist_t
*nvl
= NULL
;
4998 /* load host groups */
4999 ret
= iLoadGroupFromPs(&groupList
, HOST_GROUP
);
5000 if (ret
!= STMF_STATUS_SUCCESS
) {
5003 ret
= loadHostGroups(fd
, groupList
);
5004 if (ret
!= STMF_STATUS_SUCCESS
) {
5008 stmfFreeMemory(groupList
);
5011 /* load target groups */
5012 ret
= iLoadGroupFromPs(&groupList
, TARGET_GROUP
);
5013 if (ret
!= STMF_STATUS_SUCCESS
) {
5016 ret
= loadTargetGroups(fd
, groupList
);
5017 if (ret
!= STMF_STATUS_SUCCESS
) {
5021 stmfFreeMemory(groupList
);
5024 /* Get the guid list */
5025 ret
= psGetLogicalUnitList(&guidList
);
5027 case STMF_PS_SUCCESS
:
5028 ret
= STMF_STATUS_SUCCESS
;
5030 case STMF_PS_ERROR_NOT_FOUND
:
5031 ret
= STMF_ERROR_NOT_FOUND
;
5033 case STMF_PS_ERROR_BUSY
:
5034 ret
= STMF_ERROR_BUSY
;
5036 case STMF_PS_ERROR_SERVICE_NOT_FOUND
:
5037 ret
= STMF_ERROR_SERVICE_NOT_FOUND
;
5039 case STMF_PS_ERROR_VERSION_MISMATCH
:
5040 ret
= STMF_ERROR_SERVICE_DATA_VERSION
;
5043 ret
= STMF_STATUS_ERROR
;
5047 if (ret
!= STMF_STATUS_SUCCESS
) {
5052 * We have the guid list, now get the corresponding
5053 * view entries for each guid
5055 for (i
= 0; i
< guidList
->cnt
; i
++) {
5056 ret
= psGetViewEntryList(&guidList
->guid
[i
], &viewEntryList
);
5058 case STMF_PS_SUCCESS
:
5059 ret
= STMF_STATUS_SUCCESS
;
5061 case STMF_PS_ERROR_NOT_FOUND
:
5062 ret
= STMF_ERROR_NOT_FOUND
;
5064 case STMF_PS_ERROR_BUSY
:
5065 ret
= STMF_ERROR_BUSY
;
5067 case STMF_PS_ERROR_SERVICE_NOT_FOUND
:
5068 ret
= STMF_ERROR_SERVICE_NOT_FOUND
;
5070 case STMF_PS_ERROR_VERSION_MISMATCH
:
5071 ret
= STMF_ERROR_SERVICE_DATA_VERSION
;
5074 ret
= STMF_STATUS_ERROR
;
5077 if (ret
!= STMF_STATUS_SUCCESS
) {
5080 for (j
= 0; j
< viewEntryList
->cnt
; j
++) {
5081 ret
= addViewEntryIoctl(fd
, &guidList
->guid
[i
],
5082 &viewEntryList
->ve
[j
]);
5083 if (ret
!= STMF_STATUS_SUCCESS
) {
5089 /* get the list of providers that have data */
5090 ret
= psGetProviderDataList(&providerList
);
5092 case STMF_PS_SUCCESS
:
5093 ret
= STMF_STATUS_SUCCESS
;
5095 case STMF_PS_ERROR_NOT_FOUND
:
5096 ret
= STMF_ERROR_NOT_FOUND
;
5098 case STMF_PS_ERROR_BUSY
:
5099 ret
= STMF_ERROR_BUSY
;
5101 case STMF_PS_ERROR_SERVICE_NOT_FOUND
:
5102 ret
= STMF_ERROR_SERVICE_NOT_FOUND
;
5104 case STMF_PS_ERROR_VERSION_MISMATCH
:
5105 ret
= STMF_ERROR_SERVICE_DATA_VERSION
;
5108 ret
= STMF_STATUS_ERROR
;
5111 if (ret
!= STMF_STATUS_SUCCESS
) {
5115 for (i
= 0; i
< providerList
->cnt
; i
++) {
5116 providerType
= providerList
->provider
[i
].providerType
;
5117 ret
= psGetProviderData(providerList
->provider
[i
].name
,
5118 &nvl
, providerType
, NULL
);
5120 case STMF_PS_SUCCESS
:
5121 ret
= STMF_STATUS_SUCCESS
;
5123 case STMF_PS_ERROR_NOT_FOUND
:
5124 ret
= STMF_ERROR_NOT_FOUND
;
5126 case STMF_PS_ERROR_BUSY
:
5127 ret
= STMF_ERROR_BUSY
;
5129 case STMF_PS_ERROR_SERVICE_NOT_FOUND
:
5130 ret
= STMF_ERROR_SERVICE_NOT_FOUND
;
5132 case STMF_PS_ERROR_VERSION_MISMATCH
:
5133 ret
= STMF_ERROR_SERVICE_DATA_VERSION
;
5136 ret
= STMF_STATUS_ERROR
;
5139 if (ret
!= STMF_STATUS_SUCCESS
) {
5143 /* call setProviderData */
5144 ret
= setProviderData(fd
, providerList
->provider
[i
].name
, nvl
,
5145 providerType
, NULL
);
5147 case STMF_PS_SUCCESS
:
5148 ret
= STMF_STATUS_SUCCESS
;
5150 case STMF_PS_ERROR_NOT_FOUND
:
5151 ret
= STMF_ERROR_NOT_FOUND
;
5153 case STMF_PS_ERROR_BUSY
:
5154 ret
= STMF_ERROR_BUSY
;
5156 case STMF_PS_ERROR_SERVICE_NOT_FOUND
:
5157 ret
= STMF_ERROR_SERVICE_NOT_FOUND
;
5159 case STMF_PS_ERROR_VERSION_MISMATCH
:
5160 ret
= STMF_ERROR_SERVICE_DATA_VERSION
;
5163 ret
= STMF_STATUS_ERROR
;
5166 if (ret
!= STMF_STATUS_SUCCESS
) {
5174 if (groupList
!= NULL
) {
5177 if (guidList
!= NULL
) {
5180 if (viewEntryList
!= NULL
) {
5181 free(viewEntryList
);
5190 * Purpose - Get the alua state
5194 stmfGetAluaState(boolean_t
*enabled
, uint32_t *node
)
5196 int ret
= STMF_STATUS_SUCCESS
;
5198 stmf_iocdata_t stmfIoctl
= {0};
5199 stmf_alua_state_desc_t alua_state
= {0};
5202 if (enabled
== NULL
|| node
== NULL
) {
5203 return (STMF_ERROR_INVALID_ARG
);
5207 * Open control node for stmf
5209 if ((ret
= openStmf(OPEN_STMF
, &fd
)) != STMF_STATUS_SUCCESS
)
5213 * Issue ioctl to get the stmf state
5215 stmfIoctl
.stmf_version
= STMF_VERSION_1
;
5216 stmfIoctl
.stmf_obuf_size
= sizeof (alua_state
);
5217 stmfIoctl
.stmf_obuf
= (uint64_t)(unsigned long)&alua_state
;
5218 ioctlRet
= ioctl(fd
, STMF_IOCTL_GET_ALUA_STATE
, &stmfIoctl
);
5222 if (ioctlRet
!= 0) {
5225 ret
= STMF_ERROR_BUSY
;
5229 ret
= STMF_ERROR_PERM
;
5233 "getStmfState:ioctl errno(%d)", errno
);
5234 ret
= STMF_STATUS_ERROR
;
5238 if (alua_state
.alua_state
== 1) {
5243 *node
= alua_state
.alua_node
;
5252 * Purpose - set the alua state to enabled/disabled
5256 stmfSetAluaState(boolean_t enabled
, uint32_t node
)
5258 int ret
= STMF_STATUS_SUCCESS
;
5260 stmf_iocdata_t stmfIoctl
= {0};
5261 stmf_alua_state_desc_t alua_state
= {0};
5264 if ((enabled
!= B_TRUE
&& enabled
!= B_FALSE
) || (node
> 1)) {
5265 return (STMF_ERROR_INVALID_ARG
);
5269 alua_state
.alua_state
= 1;
5272 alua_state
.alua_node
= node
;
5275 * Open control node for stmf
5277 if ((ret
= openStmf(OPEN_STMF
, &fd
)) != STMF_STATUS_SUCCESS
)
5281 * Issue ioctl to get the stmf state
5283 stmfIoctl
.stmf_version
= STMF_VERSION_1
;
5284 stmfIoctl
.stmf_ibuf_size
= sizeof (alua_state
);
5285 stmfIoctl
.stmf_ibuf
= (uint64_t)(unsigned long)&alua_state
;
5286 ioctlRet
= ioctl(fd
, STMF_IOCTL_SET_ALUA_STATE
, &stmfIoctl
);
5290 if (ioctlRet
!= 0) {
5293 ret
= STMF_ERROR_BUSY
;
5297 ret
= STMF_ERROR_PERM
;
5301 "getStmfState:ioctl errno(%d)", errno
);
5302 ret
= STMF_STATUS_ERROR
;
5306 if (!enabled
&& ret
== STMF_STATUS_SUCCESS
) {
5307 deleteNonActiveLus();
5314 deleteNonActiveLus()
5318 stmfGuidList
*luList
;
5319 luResource hdl
= NULL
;
5321 size_t propValSize
= sizeof (propVal
);
5323 stmfRet
= stmfGetLogicalUnitList(&luList
);
5324 if (stmfRet
!= STMF_STATUS_SUCCESS
) {
5328 for (i
= 0; i
< luList
->cnt
; i
++) {
5329 stmfRet
= stmfGetLuResource(&luList
->guid
[i
], &hdl
);
5330 if (stmfRet
!= STMF_STATUS_SUCCESS
) {
5333 stmfRet
= stmfGetLuProp(hdl
, STMF_LU_PROP_ACCESS_STATE
, propVal
,
5335 if (stmfRet
!= STMF_STATUS_SUCCESS
) {
5338 if (propVal
[0] == '0') {
5339 (void) stmfFreeLuResource(hdl
);
5343 (void) stmfDeleteLu(&luList
->guid
[i
]);
5344 (void) stmfFreeLuResource(hdl
);
5349 stmfFreeMemory(luList
);
5350 (void) stmfFreeLuResource(hdl
);
5356 * Purpose - load the configuration data from smf into stmf
5360 stmfLoadConfig(void)
5362 int ret
= STMF_STATUS_SUCCESS
;
5364 stmf_state_desc_t stmfStateSet
;
5367 if (iGetPersistMethod() == STMF_PERSIST_NONE
) {
5368 stmfStateSet
.state
= STMF_STATE_OFFLINE
;
5370 if ((ret
= openStmf(OPEN_EXCL_STMF
, &fd
))
5371 != STMF_STATUS_SUCCESS
) {
5375 * Configuration not stored persistently; nothing to
5376 * initialize so do not set to STMF_CONFIG_INIT.
5378 stmfStateSet
.config_state
= STMF_CONFIG_INIT_DONE
;
5382 /* Check to ensure service exists */
5383 if (psCheckService() != STMF_STATUS_SUCCESS
) {
5384 return (STMF_ERROR_SERVICE_NOT_FOUND
);
5387 ret
= stmfGetState(&state
);
5388 if (ret
== STMF_STATUS_SUCCESS
) {
5389 if (state
.operationalState
!= STMF_SERVICE_STATE_OFFLINE
) {
5390 return (STMF_ERROR_SERVICE_ONLINE
);
5393 return (STMF_STATUS_ERROR
);
5397 stmfStateSet
.state
= STMF_STATE_OFFLINE
;
5398 stmfStateSet
.config_state
= STMF_CONFIG_INIT
;
5401 * Open control node for stmf
5403 if ((ret
= openStmf(OPEN_EXCL_STMF
, &fd
)) != STMF_STATUS_SUCCESS
)
5406 ret
= setStmfState(fd
, &stmfStateSet
, STMF_SERVICE_TYPE
);
5407 if (ret
!= STMF_STATUS_SUCCESS
) {
5411 /* Load the persistent configuration data */
5412 ret
= loadStore(fd
);
5417 stmfStateSet
.state
= STMF_STATE_OFFLINE
;
5418 stmfStateSet
.config_state
= STMF_CONFIG_INIT_DONE
;
5421 if (ret
== STMF_STATUS_SUCCESS
) {
5422 ret
= setStmfState(fd
, &stmfStateSet
, STMF_SERVICE_TYPE
);
5432 * stmfState - pointer to stmf_state_desc_t structure. Will contain the state
5433 * information of the stmf service on success.
5436 getStmfState(stmf_state_desc_t
*stmfState
)
5438 int ret
= STMF_STATUS_SUCCESS
;
5441 stmf_iocdata_t stmfIoctl
;
5444 * Open control node for stmf
5446 if ((ret
= openStmf(OPEN_STMF
, &fd
)) != STMF_STATUS_SUCCESS
)
5449 bzero(&stmfIoctl
, sizeof (stmfIoctl
));
5451 * Issue ioctl to get the stmf state
5453 stmfIoctl
.stmf_version
= STMF_VERSION_1
;
5454 stmfIoctl
.stmf_ibuf_size
= sizeof (stmf_state_desc_t
);
5455 stmfIoctl
.stmf_ibuf
= (uint64_t)(unsigned long)stmfState
;
5456 stmfIoctl
.stmf_obuf_size
= sizeof (stmf_state_desc_t
);
5457 stmfIoctl
.stmf_obuf
= (uint64_t)(unsigned long)stmfState
;
5458 ioctlRet
= ioctl(fd
, STMF_IOCTL_GET_STMF_STATE
, &stmfIoctl
);
5462 if (ioctlRet
!= 0) {
5465 ret
= STMF_ERROR_BUSY
;
5469 ret
= STMF_ERROR_PERM
;
5473 "getStmfState:ioctl errno(%d)", errno
);
5474 ret
= STMF_STATUS_ERROR
;
5485 * stmfState - pointer to caller set state structure
5486 * objectType - one of:
5492 setStmfState(int fd
, stmf_state_desc_t
*stmfState
, int objectType
)
5494 int ret
= STMF_STATUS_SUCCESS
;
5497 stmf_iocdata_t stmfIoctl
;
5499 switch (objectType
) {
5500 case LOGICAL_UNIT_TYPE
:
5501 cmd
= STMF_IOCTL_SET_LU_STATE
;
5504 cmd
= STMF_IOCTL_SET_TARGET_PORT_STATE
;
5506 case STMF_SERVICE_TYPE
:
5507 cmd
= STMF_IOCTL_SET_STMF_STATE
;
5510 ret
= STMF_STATUS_ERROR
;
5514 bzero(&stmfIoctl
, sizeof (stmfIoctl
));
5516 * Issue ioctl to set the stmf state
5518 stmfIoctl
.stmf_version
= STMF_VERSION_1
;
5519 stmfIoctl
.stmf_ibuf_size
= sizeof (stmf_state_desc_t
);
5520 stmfIoctl
.stmf_ibuf
= (uint64_t)(unsigned long)stmfState
;
5521 ioctlRet
= ioctl(fd
, cmd
, &stmfIoctl
);
5522 if (ioctlRet
!= 0) {
5525 ret
= STMF_ERROR_BUSY
;
5529 ret
= STMF_ERROR_PERM
;
5532 ret
= STMF_ERROR_NOT_FOUND
;
5536 "setStmfState:ioctl errno(%d)", errno
);
5537 ret
= STMF_STATUS_ERROR
;
5545 stmfSetStmfProp(uint8_t propType
, char *propVal
)
5547 int ret
= STMF_STATUS_SUCCESS
;
5549 case STMF_DEFAULT_LU_STATE
:
5551 case STMF_DEFAULT_TARGET_PORT_STATE
:
5554 return (STMF_ERROR_INVALID_ARG
);
5556 ret
= psSetStmfProp(propType
, propVal
);
5558 case STMF_PS_SUCCESS
:
5559 ret
= STMF_STATUS_SUCCESS
;
5561 case STMF_PS_ERROR_BUSY
:
5562 ret
= STMF_ERROR_BUSY
;
5566 "stmfSetStmfProp:psSetStmfProp:error(%d)",
5568 ret
= STMF_STATUS_ERROR
;
5576 stmfGetStmfProp(uint8_t propType
, char *propVal
, size_t *propLen
)
5578 int ret
= STMF_STATUS_SUCCESS
;
5579 char prop
[MAXNAMELEN
] = {0};
5582 if (propVal
== NULL
|| propLen
== NULL
) {
5583 return (STMF_ERROR_INVALID_ARG
);
5586 case STMF_DEFAULT_LU_STATE
:
5588 case STMF_DEFAULT_TARGET_PORT_STATE
:
5591 return (STMF_ERROR_INVALID_ARG
);
5593 ret
= psGetStmfProp(propType
, prop
);
5594 if ((reqLen
= strlcpy(propVal
, prop
, *propLen
)) >= *propLen
) {
5595 *propLen
= reqLen
+ 1;
5596 return (STMF_ERROR_INVALID_ARG
);
5600 case STMF_PS_SUCCESS
:
5601 ret
= STMF_STATUS_SUCCESS
;
5603 case STMF_PS_ERROR_BUSY
:
5604 ret
= STMF_ERROR_BUSY
;
5606 case STMF_PS_ERROR_NOT_FOUND
:
5607 ret
= STMF_ERROR_NOT_FOUND
;
5611 "stmfGetStmfProp:psGetStmfProp:error(%d)",
5613 ret
= STMF_STATUS_ERROR
;
5620 setStmfProp(stmf_set_props_t
*stmf_set_props
)
5622 char propVal
[MAXNAMELEN
] = {0};
5624 if ((ret
= psGetStmfProp(STMF_DEFAULT_LU_STATE
, propVal
)) ==
5626 if (strncmp(propVal
, "offline", strlen(propVal
)) == 0) {
5627 stmf_set_props
->default_lu_state_value
=
5630 stmf_set_props
->default_lu_state_value
=
5635 "DefaultLuState:psSetStmfProp:error(%d)", ret
);
5639 if ((ret
= psGetStmfProp(STMF_DEFAULT_TARGET_PORT_STATE
, propVal
)) ==
5641 if (strncmp(propVal
, "offline", strlen(propVal
)) == 0) {
5642 stmf_set_props
->default_target_state_value
=
5645 stmf_set_props
->default_target_state_value
=
5650 "DefaultTargetPortState:psSetStmfProp:error(%d)", ret
);
5655 case STMF_PS_SUCCESS
:
5656 ret
= STMF_STATUS_SUCCESS
;
5658 case STMF_PS_ERROR_NOT_FOUND
:
5659 ret
= STMF_ERROR_NOT_FOUND
;
5661 case STMF_PS_ERROR_BUSY
:
5662 ret
= STMF_ERROR_BUSY
;
5665 ret
= STMF_STATUS_ERROR
;
5672 loadStmfProp(int fd
)
5674 int ret
= STMF_STATUS_SUCCESS
;
5676 stmf_iocdata_t stmfIoctl
= {0};
5677 stmf_set_props_t
*stmf_set_props
= NULL
;
5679 stmf_set_props
= (stmf_set_props_t
*)
5680 calloc(1, (sizeof (stmf_set_props_t
)));
5681 if (stmf_set_props
== NULL
) {
5682 ret
= STMF_ERROR_NOMEM
;
5686 /* Loading the default property values from smf */
5688 if ((ret
= setStmfProp(stmf_set_props
)) != STMF_STATUS_SUCCESS
)
5691 stmfIoctl
.stmf_version
= STMF_VERSION_1
;
5692 stmfIoctl
.stmf_ibuf_size
= sizeof (stmf_set_props_t
);
5693 stmfIoctl
.stmf_ibuf
=
5694 (uint64_t)(unsigned long)stmf_set_props
;
5696 ioctlRet
= ioctl(fd
, STMF_IOCTL_SET_STMF_PROPS
,
5699 if (ioctlRet
!= 0) {
5702 ret
= STMF_ERROR_BUSY
;
5706 ret
= STMF_ERROR_PERM
;
5709 ret
= STMF_ERROR_NOT_FOUND
;
5713 "setDefaultStmfState:"
5714 "ioctl errno(%d)", errno
);
5715 ret
= STMF_STATUS_ERROR
;
5720 if (stmf_set_props
!= NULL
) {
5721 free(stmf_set_props
);
5727 stmfLoadStmfProps(void)
5729 int ret
= STMF_STATUS_SUCCESS
;
5731 /* open control node for stmf */
5732 if ((ret
= openStmf(OPEN_EXCL_STMF
, &fd
))
5733 != STMF_STATUS_SUCCESS
) {
5736 ret
= loadStmfProp(fd
);
5740 if (ret
!= STMF_STATUS_SUCCESS
) {
5742 "stmfLoadStmfProps:Failed");
5750 * Purpose: Online stmf service
5759 stmf_state_desc_t iState
;
5761 ret
= stmfGetState(&state
);
5762 if (ret
== STMF_STATUS_SUCCESS
) {
5763 if (state
.operationalState
== STMF_SERVICE_STATE_ONLINE
) {
5764 return (STMF_ERROR_SERVICE_ONLINE
);
5767 return (STMF_STATUS_ERROR
);
5769 iState
.state
= STMF_STATE_ONLINE
;
5770 iState
.config_state
= STMF_CONFIG_NONE
;
5772 * Open control node for stmf
5773 * to make call to setStmfState()
5775 if ((ret
= openStmf(OPEN_EXCL_STMF
, &fd
)) != STMF_STATUS_SUCCESS
)
5777 ret
= setStmfState(fd
, &iState
, STMF_SERVICE_TYPE
);
5785 * Purpose: Offline stmf service
5794 stmf_state_desc_t iState
;
5796 ret
= stmfGetState(&state
);
5797 if (ret
== STMF_STATUS_SUCCESS
) {
5798 if (state
.operationalState
== STMF_SERVICE_STATE_OFFLINE
) {
5799 return (STMF_ERROR_SERVICE_OFFLINE
);
5802 return (STMF_STATUS_ERROR
);
5804 iState
.state
= STMF_STATE_OFFLINE
;
5805 iState
.config_state
= STMF_CONFIG_NONE
;
5808 * Open control node for stmf
5809 * to make call to setStmfState()
5811 if ((ret
= openStmf(OPEN_EXCL_STMF
, &fd
)) != STMF_STATUS_SUCCESS
)
5813 ret
= setStmfState(fd
, &iState
, STMF_SERVICE_TYPE
);
5822 * Purpose: Change state of target to offline
5824 * devid - devid of the target to offline
5827 stmfOfflineTarget(stmfDevid
*devid
)
5829 stmf_state_desc_t targetState
;
5830 int ret
= STMF_STATUS_SUCCESS
;
5833 if (devid
== NULL
) {
5834 return (STMF_ERROR_INVALID_ARG
);
5836 bzero(&targetState
, sizeof (targetState
));
5838 targetState
.state
= STMF_STATE_OFFLINE
;
5839 targetState
.ident
[IDENT_LENGTH_BYTE
] = devid
->identLength
;
5840 bcopy(&(devid
->ident
), &targetState
.ident
[IDENT_LENGTH_BYTE
+ 1],
5841 devid
->identLength
);
5843 * Open control node for stmf
5844 * to make call to setStmfState()
5846 if ((ret
= openStmf(OPEN_EXCL_STMF
, &fd
)) != STMF_STATUS_SUCCESS
)
5848 ret
= setStmfState(fd
, &targetState
, TARGET_TYPE
);
5854 * stmfOfflineLogicalUnit
5856 * Purpose: Change state of logical unit to offline
5858 * lu - guid of the logical unit to offline
5861 stmfOfflineLogicalUnit(stmfGuid
*lu
)
5863 stmf_state_desc_t luState
;
5864 int ret
= STMF_STATUS_SUCCESS
;
5868 return (STMF_ERROR_INVALID_ARG
);
5871 bzero(&luState
, sizeof (luState
));
5873 luState
.state
= STMF_STATE_OFFLINE
;
5874 bcopy(lu
, &luState
.ident
, sizeof (stmfGuid
));
5876 * Open control node for stmf
5877 * to make call to setStmfState()
5879 if ((ret
= openStmf(OPEN_EXCL_STMF
, &fd
)) != STMF_STATUS_SUCCESS
)
5881 ret
= setStmfState(fd
, &luState
, LOGICAL_UNIT_TYPE
);
5889 * Purpose: Change state of target to online
5891 * devid - devid of the target to online
5894 stmfOnlineTarget(stmfDevid
*devid
)
5896 stmf_state_desc_t targetState
;
5897 int ret
= STMF_STATUS_SUCCESS
;
5900 if (devid
== NULL
) {
5901 return (STMF_ERROR_INVALID_ARG
);
5903 bzero(&targetState
, sizeof (targetState
));
5905 targetState
.state
= STMF_STATE_ONLINE
;
5906 targetState
.ident
[IDENT_LENGTH_BYTE
] = devid
->identLength
;
5907 bcopy(&(devid
->ident
), &targetState
.ident
[IDENT_LENGTH_BYTE
+ 1],
5908 devid
->identLength
);
5910 * Open control node for stmf
5911 * to make call to setStmfState()
5913 if ((ret
= openStmf(OPEN_EXCL_STMF
, &fd
)) != STMF_STATUS_SUCCESS
)
5915 ret
= setStmfState(fd
, &targetState
, TARGET_TYPE
);
5921 * stmfOnlineLogicalUnit
5923 * Purpose: Change state of logical unit to online
5925 * lu - guid of the logical unit to online
5928 stmfOnlineLogicalUnit(stmfGuid
*lu
)
5930 stmf_state_desc_t luState
;
5931 int ret
= STMF_STATUS_SUCCESS
;
5935 return (STMF_ERROR_INVALID_ARG
);
5938 bzero(&luState
, sizeof (luState
));
5940 luState
.state
= STMF_STATE_ONLINE
;
5941 bcopy(lu
, &luState
.ident
, sizeof (stmfGuid
));
5943 * Open control node for stmf
5944 * to make call to setStmfState()
5946 if ((ret
= openStmf(OPEN_EXCL_STMF
, &fd
)) != STMF_STATUS_SUCCESS
)
5948 ret
= setStmfState(fd
, &luState
, LOGICAL_UNIT_TYPE
);
5954 * stmfRemoveFromHostGroup
5956 * Purpose: Removes an initiator from an initiator group
5958 * hostGroupName - name of an initiator group
5959 * hostName - name of host group member to remove
5962 stmfRemoveFromHostGroup(stmfGroupName
*hostGroupName
, stmfDevid
*hostName
)
5967 if (hostGroupName
== NULL
||
5968 (strnlen((char *)hostGroupName
, sizeof (stmfGroupName
))
5969 == sizeof (stmfGroupName
)) || hostName
== NULL
) {
5970 return (STMF_ERROR_INVALID_ARG
);
5974 ret
= initializeConfig();
5975 if (ret
!= STMF_STATUS_SUCCESS
) {
5980 * Open control node for stmf
5982 if ((ret
= openStmf(OPEN_STMF
, &fd
)) != STMF_STATUS_SUCCESS
)
5985 if ((ret
= groupMemberIoctl(fd
, STMF_IOCTL_REMOVE_HG_ENTRY
,
5986 hostGroupName
, hostName
)) != STMF_STATUS_SUCCESS
) {
5990 if (iGetPersistMethod() == STMF_PERSIST_NONE
) {
5994 ret
= psRemoveHostGroupMember((char *)hostGroupName
,
5995 (char *)hostName
->ident
);
5997 case STMF_PS_SUCCESS
:
5998 ret
= STMF_STATUS_SUCCESS
;
6000 case STMF_PS_ERROR_MEMBER_NOT_FOUND
:
6001 ret
= STMF_ERROR_MEMBER_NOT_FOUND
;
6003 case STMF_PS_ERROR_GROUP_NOT_FOUND
:
6004 ret
= STMF_ERROR_GROUP_NOT_FOUND
;
6006 case STMF_PS_ERROR_BUSY
:
6007 ret
= STMF_ERROR_BUSY
;
6009 case STMF_PS_ERROR_SERVICE_NOT_FOUND
:
6010 ret
= STMF_ERROR_SERVICE_NOT_FOUND
;
6012 case STMF_PS_ERROR_VERSION_MISMATCH
:
6013 ret
= STMF_ERROR_SERVICE_DATA_VERSION
;
6017 "stmfRemoveFromHostGroup"
6018 "psRemoveHostGroupMember:error(%d)", ret
);
6019 ret
= STMF_STATUS_ERROR
;
6029 * stmfRemoveFromTargetGroup
6031 * Purpose: Removes a local port from a local port group
6033 * targetGroupName - name of a target group
6034 * targetName - name of target to remove
6037 stmfRemoveFromTargetGroup(stmfGroupName
*targetGroupName
, stmfDevid
*targetName
)
6042 if (targetGroupName
== NULL
||
6043 (strnlen((char *)targetGroupName
, sizeof (stmfGroupName
))
6044 == sizeof (stmfGroupName
)) || targetName
== NULL
) {
6045 return (STMF_ERROR_INVALID_ARG
);
6049 ret
= initializeConfig();
6050 if (ret
!= STMF_STATUS_SUCCESS
) {
6055 * Open control node for stmf
6057 if ((ret
= openStmf(OPEN_STMF
, &fd
)) != STMF_STATUS_SUCCESS
)
6060 if ((ret
= groupMemberIoctl(fd
, STMF_IOCTL_REMOVE_TG_ENTRY
,
6061 targetGroupName
, targetName
)) != STMF_STATUS_SUCCESS
) {
6065 if (iGetPersistMethod() == STMF_PERSIST_NONE
) {
6069 ret
= psRemoveTargetGroupMember((char *)targetGroupName
,
6070 (char *)targetName
->ident
);
6072 case STMF_PS_SUCCESS
:
6073 ret
= STMF_STATUS_SUCCESS
;
6075 case STMF_PS_ERROR_MEMBER_NOT_FOUND
:
6076 ret
= STMF_ERROR_MEMBER_NOT_FOUND
;
6078 case STMF_PS_ERROR_GROUP_NOT_FOUND
:
6079 ret
= STMF_ERROR_GROUP_NOT_FOUND
;
6081 case STMF_PS_ERROR_BUSY
:
6082 ret
= STMF_ERROR_BUSY
;
6084 case STMF_PS_ERROR_SERVICE_NOT_FOUND
:
6085 ret
= STMF_ERROR_SERVICE_NOT_FOUND
;
6087 case STMF_PS_ERROR_VERSION_MISMATCH
:
6088 ret
= STMF_ERROR_SERVICE_DATA_VERSION
;
6092 "stmfRemoveFromTargetGroup"
6093 "psRemoveTargetGroupMember:error(%d)", ret
);
6094 ret
= STMF_STATUS_ERROR
;
6104 * stmfRemoveViewEntry
6106 * Purpose: Removes a view entry from a logical unit
6108 * lu - guid of lu for which view entry is being removed
6109 * viewEntryIndex - index of view entry to remove
6113 stmfRemoveViewEntry(stmfGuid
*lu
, uint32_t viewEntryIndex
)
6115 int ret
= STMF_STATUS_SUCCESS
;
6118 stmf_iocdata_t stmfIoctl
;
6119 stmf_view_op_entry_t ioctlViewEntry
;
6122 return (STMF_ERROR_INVALID_ARG
);
6126 ret
= initializeConfig();
6127 if (ret
!= STMF_STATUS_SUCCESS
) {
6132 * Open control node for stmf
6134 if ((ret
= openStmf(OPEN_STMF
, &fd
)) != STMF_STATUS_SUCCESS
)
6137 bzero(&ioctlViewEntry
, sizeof (ioctlViewEntry
));
6138 ioctlViewEntry
.ve_ndx_valid
= B_TRUE
;
6139 ioctlViewEntry
.ve_ndx
= viewEntryIndex
;
6140 bcopy(lu
, &ioctlViewEntry
.ve_guid
, sizeof (stmfGuid
));
6142 bzero(&stmfIoctl
, sizeof (stmfIoctl
));
6144 * Issue ioctl to add to the view entry
6146 stmfIoctl
.stmf_version
= STMF_VERSION_1
;
6147 stmfIoctl
.stmf_ibuf_size
= sizeof (ioctlViewEntry
);
6148 stmfIoctl
.stmf_ibuf
= (uint64_t)(unsigned long)&ioctlViewEntry
;
6149 ioctlRet
= ioctl(fd
, STMF_IOCTL_REMOVE_VIEW_ENTRY
, &stmfIoctl
);
6150 if (ioctlRet
!= 0) {
6153 ret
= STMF_ERROR_BUSY
;
6156 ret
= STMF_ERROR_PERM
;
6159 switch (stmfIoctl
.stmf_error
) {
6160 case STMF_IOCERR_UPDATE_NEED_CFG_INIT
:
6161 ret
= STMF_ERROR_CONFIG_NONE
;
6164 ret
= STMF_ERROR_PERM
;
6170 ret
= STMF_ERROR_NOT_FOUND
;
6174 "stmfRemoveViewEntry:ioctl errno(%d)",
6176 ret
= STMF_STATUS_ERROR
;
6182 if (iGetPersistMethod() == STMF_PERSIST_NONE
) {
6186 ret
= psRemoveViewEntry(lu
, viewEntryIndex
);
6188 case STMF_PS_SUCCESS
:
6189 ret
= STMF_STATUS_SUCCESS
;
6191 case STMF_PS_ERROR_NOT_FOUND
:
6192 ret
= STMF_ERROR_NOT_FOUND
;
6194 case STMF_PS_ERROR_BUSY
:
6195 ret
= STMF_ERROR_BUSY
;
6197 case STMF_PS_ERROR_SERVICE_NOT_FOUND
:
6198 ret
= STMF_ERROR_SERVICE_NOT_FOUND
;
6200 case STMF_PS_ERROR_VERSION_MISMATCH
:
6201 ret
= STMF_ERROR_SERVICE_DATA_VERSION
;
6205 "stmfRemoveViewEntry" "psRemoveViewEntry:error(%d)",
6207 ret
= STMF_STATUS_ERROR
;
6217 * stmfSetProviderData
6219 * Purpose: set the provider data
6221 * providerName - unique name of provider
6222 * nvl - nvlist to set
6223 * providerType - type of provider for which to set data
6224 * STMF_LU_PROVIDER_TYPE
6225 * STMF_PORT_PROVIDER_TYPE
6228 stmfSetProviderData(char *providerName
, nvlist_t
*nvl
, int providerType
)
6230 return (stmfSetProviderDataProt(providerName
, nvl
, providerType
,
6235 * stmfSetProviderDataProt
6237 * Purpose: set the provider data
6239 * providerName - unique name of provider
6240 * nvl - nvlist to set
6241 * providerType - type of provider for which to set data
6242 * STMF_LU_PROVIDER_TYPE
6243 * STMF_PORT_PROVIDER_TYPE
6244 * setToken - Stale data token returned in the stmfGetProviderDataProt()
6248 stmfSetProviderDataProt(char *providerName
, nvlist_t
*nvl
, int providerType
,
6254 if (providerName
== NULL
|| nvl
== NULL
) {
6255 return (STMF_ERROR_INVALID_ARG
);
6258 if (providerType
!= STMF_LU_PROVIDER_TYPE
&&
6259 providerType
!= STMF_PORT_PROVIDER_TYPE
) {
6260 return (STMF_ERROR_INVALID_ARG
);
6264 ret
= initializeConfig();
6265 if (ret
!= STMF_STATUS_SUCCESS
) {
6270 * Open control node for stmf
6272 if ((ret
= openStmf(OPEN_STMF
, &fd
)) != STMF_STATUS_SUCCESS
)
6275 ret
= setProviderData(fd
, providerName
, nvl
, providerType
, setToken
);
6279 if (ret
!= STMF_STATUS_SUCCESS
) {
6283 if (iGetPersistMethod() == STMF_PERSIST_NONE
) {
6287 /* setting driver provider data successful. Now persist it */
6288 ret
= psSetProviderData(providerName
, nvl
, providerType
, NULL
);
6290 case STMF_PS_SUCCESS
:
6291 ret
= STMF_STATUS_SUCCESS
;
6293 case STMF_PS_ERROR_EXISTS
:
6294 ret
= STMF_ERROR_EXISTS
;
6296 case STMF_PS_ERROR_BUSY
:
6297 ret
= STMF_ERROR_BUSY
;
6299 case STMF_PS_ERROR_SERVICE_NOT_FOUND
:
6300 ret
= STMF_ERROR_SERVICE_NOT_FOUND
;
6302 case STMF_PS_ERROR_VERSION_MISMATCH
:
6303 ret
= STMF_ERROR_SERVICE_DATA_VERSION
;
6305 case STMF_PS_ERROR_PROV_DATA_STALE
:
6306 ret
= STMF_ERROR_PROV_DATA_STALE
;
6310 "stmfSetProviderData"
6311 "psSetProviderData:error(%d)", ret
);
6312 ret
= STMF_STATUS_ERROR
;
6323 * Purpose: set the provider data from stmf
6325 * providerName - unique name of provider
6326 * nvl - nvlist to load/retrieve
6327 * providerType - logical unit or port provider
6328 * setToken - returned stale data token
6331 getProviderData(char *providerName
, nvlist_t
**nvl
, int providerType
,
6334 int ret
= STMF_STATUS_SUCCESS
;
6337 size_t nvlistSize
= ALLOC_PP_DATA_SIZE
;
6339 int retryCntMax
= MAX_PROVIDER_RETRY
;
6340 stmf_ppioctl_data_t ppi
= {0}, *ppi_out
= NULL
;
6341 boolean_t retry
= B_TRUE
;
6342 stmf_iocdata_t stmfIoctl
;
6344 if (providerName
== NULL
) {
6345 return (STMF_ERROR_INVALID_ARG
);
6349 * Open control node for stmf
6351 if ((ret
= openStmf(OPEN_STMF
, &fd
)) != STMF_STATUS_SUCCESS
)
6354 /* set provider name and provider type */
6355 if (strlcpy(ppi
.ppi_name
, providerName
,
6356 sizeof (ppi
.ppi_name
)) >=
6357 sizeof (ppi
.ppi_name
)) {
6358 ret
= STMF_ERROR_INVALID_ARG
;
6361 switch (providerType
) {
6362 case STMF_LU_PROVIDER_TYPE
:
6363 ppi
.ppi_lu_provider
= 1;
6365 case STMF_PORT_PROVIDER_TYPE
:
6366 ppi
.ppi_port_provider
= 1;
6369 ret
= STMF_ERROR_INVALID_ARG
;
6374 /* allocate memory for ioctl */
6375 ppi_out
= (stmf_ppioctl_data_t
*)calloc(1, nvlistSize
+
6376 sizeof (stmf_ppioctl_data_t
));
6377 if (ppi_out
== NULL
) {
6378 ret
= STMF_ERROR_NOMEM
;
6383 /* set the size of the ioctl data to allocated buffer */
6384 ppi
.ppi_data_size
= nvlistSize
;
6386 bzero(&stmfIoctl
, sizeof (stmfIoctl
));
6388 stmfIoctl
.stmf_version
= STMF_VERSION_1
;
6389 stmfIoctl
.stmf_ibuf_size
= sizeof (stmf_ppioctl_data_t
);
6390 stmfIoctl
.stmf_ibuf
= (uint64_t)(unsigned long)&ppi
;
6391 stmfIoctl
.stmf_obuf_size
= sizeof (stmf_ppioctl_data_t
) +
6393 stmfIoctl
.stmf_obuf
= (uint64_t)(unsigned long)ppi_out
;
6394 ioctlRet
= ioctl(fd
, STMF_IOCTL_GET_PP_DATA
, &stmfIoctl
);
6395 if (ioctlRet
!= 0) {
6398 ret
= STMF_ERROR_BUSY
;
6402 ret
= STMF_ERROR_PERM
;
6405 if (stmfIoctl
.stmf_error
==
6406 STMF_IOCERR_INSUFFICIENT_BUF
) {
6408 ppi_out
->ppi_data_size
;
6411 if (retryCnt
++ > retryCntMax
) {
6413 ret
= STMF_ERROR_BUSY
;
6416 STMF_STATUS_SUCCESS
;
6420 "getProviderData:ioctl"
6421 "unable to retrieve "
6423 ret
= STMF_STATUS_ERROR
;
6427 ret
= STMF_ERROR_NOT_FOUND
;
6431 "getProviderData:ioctl errno(%d)",
6433 ret
= STMF_STATUS_ERROR
;
6436 if (ret
!= STMF_STATUS_SUCCESS
)
6439 } while (retry
&& stmfIoctl
.stmf_error
== STMF_IOCERR_INSUFFICIENT_BUF
);
6441 if ((ret
= nvlist_unpack((char *)ppi_out
->ppi_data
,
6442 ppi_out
->ppi_data_size
, nvl
, 0)) != 0) {
6443 ret
= STMF_STATUS_ERROR
;
6447 /* caller has asked for new token */
6449 *setToken
= ppi_out
->ppi_token
;
6460 * Purpose: set the provider data in stmf
6462 * providerName - unique name of provider
6463 * nvl - nvlist to set
6464 * providerType - logical unit or port provider
6465 * setToken - stale data token to check if not NULL
6468 setProviderData(int fd
, char *providerName
, nvlist_t
*nvl
, int providerType
,
6471 int ret
= STMF_STATUS_SUCCESS
;
6473 size_t nvlistEncodedSize
;
6474 stmf_ppioctl_data_t
*ppi
= NULL
;
6476 char *allocatedNvBuffer
;
6477 stmf_iocdata_t stmfIoctl
;
6479 if (providerName
== NULL
) {
6480 return (STMF_ERROR_INVALID_ARG
);
6483 /* get size of encoded nvlist */
6484 if (nvlist_size(nvl
, &nvlistEncodedSize
, NV_ENCODE_XDR
) != 0) {
6485 return (STMF_STATUS_ERROR
);
6488 /* allocate memory for ioctl */
6489 ppi
= (stmf_ppioctl_data_t
*)calloc(1, nvlistEncodedSize
+
6490 sizeof (stmf_ppioctl_data_t
));
6492 return (STMF_ERROR_NOMEM
);
6496 ppi
->ppi_token_valid
= 1;
6497 ppi
->ppi_token
= *setToken
;
6500 allocatedNvBuffer
= (char *)&ppi
->ppi_data
;
6501 if (nvlist_pack(nvl
, &allocatedNvBuffer
, &nvlistEncodedSize
,
6502 NV_ENCODE_XDR
, 0) != 0) {
6503 return (STMF_STATUS_ERROR
);
6506 /* set provider name and provider type */
6507 (void) strncpy(ppi
->ppi_name
, providerName
, sizeof (ppi
->ppi_name
));
6508 switch (providerType
) {
6509 case STMF_LU_PROVIDER_TYPE
:
6510 ppi
->ppi_lu_provider
= 1;
6512 case STMF_PORT_PROVIDER_TYPE
:
6513 ppi
->ppi_port_provider
= 1;
6516 return (STMF_ERROR_INVALID_ARG
);
6519 /* set the size of the ioctl data to packed data size */
6520 ppi
->ppi_data_size
= nvlistEncodedSize
;
6522 bzero(&stmfIoctl
, sizeof (stmfIoctl
));
6524 stmfIoctl
.stmf_version
= STMF_VERSION_1
;
6526 * Subtracting 8 from the size as that is the size of the last member
6527 * of the structure where the packed data resides
6529 stmfIoctl
.stmf_ibuf_size
= nvlistEncodedSize
+
6530 sizeof (stmf_ppioctl_data_t
) - 8;
6531 stmfIoctl
.stmf_ibuf
= (uint64_t)(unsigned long)ppi
;
6532 stmfIoctl
.stmf_obuf_size
= sizeof (uint64_t);
6533 stmfIoctl
.stmf_obuf
= (uint64_t)(unsigned long)&outToken
;
6534 ioctlRet
= ioctl(fd
, STMF_IOCTL_LOAD_PP_DATA
, &stmfIoctl
);
6535 if (ioctlRet
!= 0) {
6538 ret
= STMF_ERROR_BUSY
;
6542 ret
= STMF_ERROR_PERM
;
6545 if (stmfIoctl
.stmf_error
==
6546 STMF_IOCERR_PPD_UPDATED
) {
6547 ret
= STMF_ERROR_PROV_DATA_STALE
;
6549 ret
= STMF_STATUS_ERROR
;
6554 "setProviderData:ioctl errno(%d)", errno
);
6555 ret
= STMF_STATUS_ERROR
;
6558 if (ret
!= STMF_STATUS_SUCCESS
)
6562 /* caller has asked for new token */
6564 *setToken
= outToken
;
6572 * set the persistence method in the library only or library and service
6575 stmfSetPersistMethod(uint8_t persistType
, boolean_t serviceSet
)
6577 int ret
= STMF_STATUS_SUCCESS
;
6580 (void) pthread_mutex_lock(&persistenceTypeLock
);
6581 oldPersist
= iPersistType
;
6582 if (persistType
== STMF_PERSIST_NONE
||
6583 persistType
== STMF_PERSIST_SMF
) {
6584 iLibSetPersist
= B_TRUE
;
6585 iPersistType
= persistType
;
6587 (void) pthread_mutex_unlock(&persistenceTypeLock
);
6588 return (STMF_ERROR_INVALID_ARG
);
6590 /* Is this for this library open or in SMF */
6591 if (serviceSet
== B_TRUE
) {
6592 ret
= psSetServicePersist(persistType
);
6593 if (ret
!= STMF_PS_SUCCESS
) {
6594 ret
= STMF_ERROR_PERSIST_TYPE
;
6595 /* Set to old value */
6596 iPersistType
= oldPersist
;
6599 (void) pthread_mutex_unlock(&persistenceTypeLock
);
6605 * Only returns internal state for persist. If unset, goes to ps. If that
6606 * fails, returns default setting
6612 uint8_t persistType
= 0;
6614 (void) pthread_mutex_lock(&persistenceTypeLock
);
6615 if (iLibSetPersist
) {
6616 persistType
= iPersistType
;
6619 ret
= psGetServicePersist(&persistType
);
6620 if (ret
!= STMF_PS_SUCCESS
) {
6621 /* set to default */
6622 persistType
= STMF_DEFAULT_PERSIST
;
6625 (void) pthread_mutex_unlock(&persistenceTypeLock
);
6626 return (persistType
);
6630 * Returns either library state or persistent config state depending on
6634 stmfGetPersistMethod(uint8_t *persistType
, boolean_t serviceState
)
6636 int ret
= STMF_STATUS_SUCCESS
;
6638 if (persistType
== NULL
) {
6639 return (STMF_ERROR_INVALID_ARG
);
6642 ret
= psGetServicePersist(persistType
);
6643 if (ret
!= STMF_PS_SUCCESS
) {
6644 ret
= STMF_ERROR_PERSIST_TYPE
;
6647 (void) pthread_mutex_lock(&persistenceTypeLock
);
6648 if (iLibSetPersist
) {
6649 *persistType
= iPersistType
;
6651 *persistType
= STMF_DEFAULT_PERSIST
;
6653 (void) pthread_mutex_unlock(&persistenceTypeLock
);
6662 * Purpose: Post a message to the proxy port provider
6664 * buf - buffer containing message to post
6665 * buflen - buffer length
6668 stmfPostProxyMsg(int hdl
, void *buf
, uint32_t buflen
)
6670 int ret
= STMF_STATUS_SUCCESS
;
6672 pppt_iocdata_t ppptIoctl
= {0};
6675 return (STMF_ERROR_INVALID_ARG
);
6679 * Issue ioctl to post the message
6681 ppptIoctl
.pppt_version
= PPPT_VERSION_1
;
6682 ppptIoctl
.pppt_buf_size
= buflen
;
6683 ppptIoctl
.pppt_buf
= (uint64_t)(unsigned long)buf
;
6684 ioctlRet
= ioctl(hdl
, PPPT_MESSAGE
, &ppptIoctl
);
6685 if (ioctlRet
!= 0) {
6689 ret
= STMF_ERROR_PERM
;
6692 ret
= STMF_ERROR_POST_MSG_FAILED
;
6703 * Purpose: Install door in proxy
6705 * hdl - pointer to returned handle
6706 * fd - door from door_create()
6709 stmfInitProxyDoor(int *hdl
, int door
)
6711 int ret
= STMF_STATUS_SUCCESS
;
6714 pppt_iocdata_t ppptIoctl
= {0};
6717 return (STMF_ERROR_INVALID_ARG
);
6721 * Open control node for pppt
6723 if ((ret
= openPppt(OPEN_PPPT
, &fd
)) != STMF_STATUS_SUCCESS
) {
6728 * Issue ioctl to install the door
6730 ppptIoctl
.pppt_version
= PPPT_VERSION_1
;
6731 ppptIoctl
.pppt_door_fd
= (uint32_t)door
;
6732 ioctlRet
= ioctl(fd
, PPPT_INSTALL_DOOR
, &ppptIoctl
);
6733 if (ioctlRet
!= 0) {
6737 ret
= STMF_ERROR_PERM
;
6740 ret
= STMF_ERROR_INVALID_ARG
;
6743 ret
= STMF_ERROR_DOOR_INSTALLED
;
6746 ret
= STMF_STATUS_ERROR
;
6751 /* return driver fd to caller */
6757 stmfDestroyProxyDoor(int hdl
)
6763 * validateLunNumIoctl
6765 * Purpose: Issues ioctl to check and get available lun# in view entry
6767 * viewEntry - view entry to use
6770 validateLunNumIoctl(int fd
, stmfViewEntry
*viewEntry
)
6772 int ret
= STMF_STATUS_SUCCESS
;
6774 stmf_iocdata_t stmfIoctl
;
6775 stmf_view_op_entry_t ioctlViewEntry
;
6777 bzero(&ioctlViewEntry
, sizeof (ioctlViewEntry
));
6779 * don't set ve_ndx or ve_ndx_valid as ve_ndx_valid should be
6782 ioctlViewEntry
.ve_lu_number_valid
= viewEntry
->luNbrValid
;
6783 ioctlViewEntry
.ve_all_hosts
= viewEntry
->allHosts
;
6784 ioctlViewEntry
.ve_all_targets
= viewEntry
->allTargets
;
6786 if (viewEntry
->allHosts
== B_FALSE
) {
6787 bcopy(viewEntry
->hostGroup
, &ioctlViewEntry
.ve_host_group
.name
,
6788 sizeof (stmfGroupName
));
6789 ioctlViewEntry
.ve_host_group
.name_size
=
6790 strlen((char *)viewEntry
->hostGroup
);
6792 if (viewEntry
->allTargets
== B_FALSE
) {
6793 bcopy(viewEntry
->targetGroup
,
6794 &ioctlViewEntry
.ve_target_group
.name
,
6795 sizeof (stmfGroupName
));
6796 ioctlViewEntry
.ve_target_group
.name_size
=
6797 strlen((char *)viewEntry
->targetGroup
);
6799 /* Validating the lun number */
6800 if (viewEntry
->luNbrValid
) {
6801 bcopy(viewEntry
->luNbr
, &ioctlViewEntry
.ve_lu_nbr
,
6802 sizeof (ioctlViewEntry
.ve_lu_nbr
));
6805 bzero(&stmfIoctl
, sizeof (stmfIoctl
));
6807 * Issue ioctl to validate lun# in the view entry
6809 stmfIoctl
.stmf_version
= STMF_VERSION_1
;
6810 stmfIoctl
.stmf_ibuf_size
= sizeof (ioctlViewEntry
);
6811 stmfIoctl
.stmf_ibuf
= (uint64_t)(unsigned long)&ioctlViewEntry
;
6812 stmfIoctl
.stmf_obuf_size
= sizeof (ioctlViewEntry
);
6813 stmfIoctl
.stmf_obuf
= (uint64_t)(unsigned long)&ioctlViewEntry
;
6814 ioctlRet
= ioctl(fd
, STMF_IOCTL_VALIDATE_VIEW
, &stmfIoctl
);
6816 /* save available lun number */
6817 if (!viewEntry
->luNbrValid
) {
6818 bcopy(ioctlViewEntry
.ve_lu_nbr
, viewEntry
->luNbr
,
6819 sizeof (ioctlViewEntry
.ve_lu_nbr
));
6821 if (ioctlRet
!= 0) {
6824 ret
= STMF_ERROR_BUSY
;
6827 ret
= STMF_ERROR_PERM
;
6830 switch (stmfIoctl
.stmf_error
) {
6831 case STMF_IOCERR_UPDATE_NEED_CFG_INIT
:
6832 ret
= STMF_ERROR_CONFIG_NONE
;
6835 ret
= STMF_ERROR_PERM
;
6840 switch (stmfIoctl
.stmf_error
) {
6841 case STMF_IOCERR_LU_NUMBER_IN_USE
:
6842 ret
= STMF_ERROR_LUN_IN_USE
;
6844 case STMF_IOCERR_VIEW_ENTRY_CONFLICT
:
6845 ret
= STMF_ERROR_VE_CONFLICT
;
6847 case STMF_IOCERR_UPDATE_NEED_CFG_INIT
:
6848 ret
= STMF_ERROR_CONFIG_NONE
;
6850 case STMF_IOCERR_INVALID_HG
:
6851 ret
= STMF_ERROR_INVALID_HG
;
6853 case STMF_IOCERR_INVALID_TG
:
6854 ret
= STMF_ERROR_INVALID_TG
;
6860 stmfIoctl
.stmf_error
);
6861 ret
= STMF_STATUS_ERROR
;
6873 * Purpose: Validate or get lun # base on TG, HG of view entry
6875 * viewEntry - view entry structure to use
6878 stmfValidateView(stmfViewEntry
*viewEntry
)
6882 stmfViewEntry iViewEntry
;
6884 if (viewEntry
== NULL
) {
6885 return (STMF_ERROR_INVALID_ARG
);
6888 /* initialize and set internal view entry */
6889 bzero(&iViewEntry
, sizeof (iViewEntry
));
6891 if (!viewEntry
->allHosts
) {
6892 bcopy(viewEntry
->hostGroup
, iViewEntry
.hostGroup
,
6893 sizeof (iViewEntry
.hostGroup
));
6895 iViewEntry
.allHosts
= B_TRUE
;
6898 if (!viewEntry
->allTargets
) {
6899 bcopy(viewEntry
->targetGroup
, iViewEntry
.targetGroup
,
6900 sizeof (iViewEntry
.targetGroup
));
6902 iViewEntry
.allTargets
= B_TRUE
;
6905 if (viewEntry
->luNbrValid
) {
6906 iViewEntry
.luNbrValid
= B_TRUE
;
6907 bcopy(viewEntry
->luNbr
, iViewEntry
.luNbr
,
6908 sizeof (iViewEntry
.luNbr
));
6912 * set users return view entry index valid flag to false
6913 * in case of failure
6915 viewEntry
->veIndexValid
= B_FALSE
;
6917 /* Check to ensure service exists */
6918 if (psCheckService() != STMF_STATUS_SUCCESS
) {
6919 return (STMF_ERROR_SERVICE_NOT_FOUND
);
6923 ret
= initializeConfig();
6924 if (ret
!= STMF_STATUS_SUCCESS
) {
6929 * Open control node for stmf
6931 if ((ret
= openStmf(OPEN_STMF
, &fd
)) != STMF_STATUS_SUCCESS
)
6935 * Validate lun# in the view entry from the driver
6937 ret
= validateLunNumIoctl(fd
, &iViewEntry
);
6940 /* save available lun number */
6941 if (!viewEntry
->luNbrValid
) {
6942 bcopy(iViewEntry
.luNbr
, viewEntry
->luNbr
,
6943 sizeof (iViewEntry
.luNbr
));