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.
37 #include <libnvpair.h>
42 * This file's functions are responsible for all store and retrieve operations
43 * against the STMF smf(5) database. The following shows the currently defined
44 * schema for the STMF database:
46 * Description of property groups for service: svc:/system/stmf
50 * 1. Property Group: host_groups
51 * Properties: group_name-<N> where <N> is an unsigned integer
53 * contains: group name
54 * group_name-<N>-member_list where <N> is an unsigned
55 * integer matching a group_name-<N> property.
57 * contains: list of members
60 * Contains the host group names as well as the host group members
61 * for each host group.
63 * 2. Property Group: target_groups
64 * Properties: group_name-<N> where <N> is an unsigned integer
66 * contains: group name
67 * group_name-<N>-member_list where <N> is an unsigned
68 * integer matching a group_name-<N> property.
70 * contains: list of members
73 * Contains the target group names as well as the target group
74 * members for each target group.
76 * 3. Property Group: lu-<GUID>
77 * where <GUID> is a 32 character hexadecimal string.
80 * contains: the number of current view entries
81 * view-entry-<N>-<GUID> where <N> is an unsigned integer
83 * contains: nothing. Used as reference to the view
84 * entry property group
87 * Contains the references to each view entry. One lu-<GUID>
88 * property group will exist for each logical unit with 1 or more
90 * Potentially can hold any other data that can be managed on a per
93 * 4. Property Group: view_entry-<N>-<GUID> (matches property in lu-<GUID>
95 * Properties: all_hosts
97 * contains: when true, the value of host_group is
101 * contains: when true, the value of target_group is
105 * contains: host group for logical unit mapping and
109 * contains: target group for logical unit mapping and
113 * contains: the 8-byte SCSI logical unit number for
114 * mapping and masking purposes
116 * One "view_entry-<N>-<GUID>" property group will exist for each
117 * view entry in the system. This property group name maps
118 * directly to the "lu-<GUID>" property group with a matching
121 * 5. Property Group: provider_data_pg_<provider-name>
122 * where <provider-name> is the name of the provider
123 * registered with stmf.
124 * Properties: provider_data_prop-<N>
125 * where <N> is a sequential identifier for the data
128 * contains: up to STMF_PROVIDER_DATA_PROP_SIZE bytes
129 * of nvlist packed data.
130 * provider_data_count
132 * contains: the number of provider data chunks
135 * contains: STMF_PORT_PROVIDER_TYPE or
136 * STMF_LU_PROVIDER_TYPE
139 * Holds the nvlist packed provider data set via
140 * stmfSetProviderData and retrieved via stmfGetProviderData. Data
141 * is stored in STMF_PROVIDER_DATA_PROP_SIZE chunks. On retrieve,
142 * these chunks are reassembled and unpacked.
146 static int iPsInit(scf_handle_t
**, scf_service_t
**);
147 static int iPsCreateDeleteGroup(char *, char *, int);
148 static int iPsAddRemoveGroupMember(char *, char *, char *, int);
149 static int iPsGetGroupList(char *, stmfGroupList
**);
150 static int iPsGetGroupMemberList(char *, char *, stmfGroupProperties
**);
151 static int iPsAddViewEntry(char *, char *, stmfViewEntry
*);
152 static int iPsAddRemoveLuViewEntry(char *, char *, int);
153 static int iPsGetViewEntry(char *, stmfViewEntry
*);
154 static int iPsGetActualGroupName(char *, char *, char *);
155 static int iPsGetServiceVersion(uint64_t *, scf_handle_t
*, scf_service_t
*);
156 static int iPsGetSetPersistType(uint8_t *, scf_handle_t
*, scf_service_t
*,
158 static int iPsGetSetStmfProp(int, char *, int);
159 static int viewEntryCompare(const void *, const void *);
160 static int holdSignal(sigset_t
*);
161 static int releaseSignal(sigset_t
*);
162 static void sigHandler();
164 static pthread_mutex_t sigSetLock
= PTHREAD_MUTEX_INITIALIZER
;
167 sigset_t signalsCaught
;
169 struct sigaction currentActionQuit
;
170 struct sigaction currentActionTerm
;
171 struct sigaction currentActionInt
;
173 boolean_t actionSet
= B_FALSE
;
176 * Version info for the SMF schema
178 #define STMF_SMF_VERSION 1
181 * Note: Do not change these property names and size values.
182 * They represent fields in the persistent config and once modified
183 * will have a nasty side effect of invalidating the existing store.
184 * If you do need to change them, you'll need to use the versioning above
185 * to retain backward compatiblity with the previous configuration schema.
188 /* BEGIN STORE PROPERTY DEFINITIONS */
190 * Property Group Names and prefixes
192 #define STMF_HOST_GROUPS "host_groups"
193 #define STMF_TARGET_GROUPS "target_groups"
194 #define STMF_VE_PREFIX "view_entry"
195 #define STMF_LU_PREFIX "lu"
196 #define STMF_DATA_GROUP "stmf_data"
199 * Property names and prefix for logical unit property group
201 #define STMF_VE_CNT "ve_cnt"
202 #define STMF_GROUP_PREFIX "group_name"
203 #define STMF_MEMBER_LIST_SUFFIX "member_list"
204 #define STMF_VERSION_NAME "version_name"
205 #define STMF_PERSIST_TYPE "persist_method"
207 /* Property names for stmf properties */
209 #define DEFAULT_LU_STATE "default_lu_state"
210 #define DEFAULT_TARGET_PORT_STATE "default_target_state"
213 * Property names for view entry
215 #define STMF_VE_ALLHOSTS "all_hosts"
216 #define STMF_VE_HOSTGROUP "host_group"
217 #define STMF_VE_ALLTARGETS "all_targets"
218 #define STMF_VE_TARGETGROUP "target_group"
219 #define STMF_VE_LUNBR "lu_nbr"
221 /* Property group suffix for provider data */
222 #define STMF_PROVIDER_DATA_PREFIX "provider_data_pg_"
223 #define STMF_PROVIDER_DATA_PROP_PREFIX "provider_data_prop"
224 #define STMF_PROVIDER_DATA_PROP_NAME_SIZE 256
225 #define STMF_PROVIDER_DATA_PROP_TYPE "provider_type"
226 #define STMF_PROVIDER_DATA_PROP_SET_COUNT "provider_data_set_cnt"
227 #define STMF_PROVIDER_DATA_PROP_COUNT "provider_data_cnt"
230 #define STMF_SMF_READ_ATTR "solaris.smf.read.stmf"
232 #define STMF_PS_PERSIST_NONE "none"
233 #define STMF_PS_PERSIST_SMF "smf"
234 #define STMF_PROVIDER_DATA_PROP_SIZE 4000
236 #define STMF_PS_LU_ONLINE "default_lu_online"
237 #define STMF_PS_LU_OFFLINE "default_lu_offline"
238 #define STMF_PS_TARGET_PORT_ONLINE "default_target_online"
239 #define STMF_PS_TARGET_PORT_OFFLINE "default_target_offline"
241 /* END STORE PROPERTY DEFINITIONS */
244 #define STMF_SERVICE "system/stmf"
246 /* limits and flag values */
247 #define GROUP_MEMBER_ALLOC 100
248 #define VIEW_ENTRY_STRUCT_CNT 6
249 #define VIEW_ENTRY_PG_SIZE 256
250 #define LOGICAL_UNIT_PG_SIZE 256
251 #define VIEW_ENTRY_MAX UINT32_MAX
252 #define GROUP_MAX UINT64_MAX
261 * Catch the signal and set the global signalsCaught to the signal received
263 * signalsCaught will be used by releaseSignal to raise this signal when
264 * we're done processing our critical code.
270 (void) sigaddset(&signalsCaught
, sig
);
274 * iPsAddRemoveGroupMember
276 * Add or remove a member for a given group
278 * pgName - Property group name
279 * groupName - group name to which the member is added/removed
280 * memberName - member to be added/removed
281 * addRemoveFlag - ADD/REMOVE
284 * STMF_PS_SUCCESS on success
285 * STMF_PS_ERROR_* on failure
288 iPsAddRemoveGroupMember(char *pgName
, char *groupName
, char *memberName
,
291 scf_handle_t
*handle
= NULL
;
292 scf_service_t
*svc
= NULL
;
293 scf_propertygroup_t
*pg
= NULL
;
294 scf_property_t
*prop
= NULL
;
295 scf_value_t
*valueLookup
= NULL
;
296 scf_value_t
**valueSet
= NULL
;
297 scf_iter_t
*valueIter
= NULL
;
298 scf_transaction_t
*tran
= NULL
;
299 scf_transaction_entry_t
*entry
= NULL
;
302 int valueArraySize
= 0;
303 int ret
= STMF_PS_SUCCESS
;
304 char buf
[STMF_IDENT_LENGTH
];
306 boolean_t found
= B_FALSE
;
308 assert(pgName
!= NULL
&& groupName
!= NULL
&& memberName
!= NULL
);
311 * Init the service handle
313 ret
= iPsInit(&handle
, &svc
);
314 if (ret
!= STMF_PS_SUCCESS
) {
319 * Allocate scf resources
321 if (((pg
= scf_pg_create(handle
)) == NULL
) ||
322 ((tran
= scf_transaction_create(handle
)) == NULL
) ||
323 ((entry
= scf_entry_create(handle
)) == NULL
) ||
324 ((prop
= scf_property_create(handle
)) == NULL
) ||
325 ((valueIter
= scf_iter_create(handle
)) == NULL
)) {
326 syslog(LOG_ERR
, "scf alloc resource failed - %s",
327 scf_strerror(scf_error()));
333 * Get the service property group handle
335 if (scf_service_get_pg(svc
, pgName
, pg
) == -1) {
336 if (scf_error() == SCF_ERROR_NOT_FOUND
) {
337 ret
= STMF_PS_ERROR_NOT_FOUND
;
341 syslog(LOG_ERR
, "get pg %s failed - %s",
342 pgName
, scf_strerror(scf_error()));
348 * Begin the transaction
350 if (scf_transaction_start(tran
, pg
) == -1) {
351 syslog(LOG_ERR
, "start transaction for %s failed - %s",
352 pgName
, scf_strerror(scf_error()));
358 * We're changing an existing property by adding a propval
359 * There are no add semantics in libscf for a property value. We'll
360 * need to read in the current properties and apply them all to the
361 * set and then add the one we were asked to add or omit the one
362 * we were asked to remove.
364 if (scf_transaction_property_change(tran
, entry
, groupName
,
365 SCF_TYPE_USTRING
) == -1) {
366 if (scf_error() == SCF_ERROR_NOT_FOUND
) {
367 ret
= STMF_PS_ERROR_GROUP_NOT_FOUND
;
370 syslog(LOG_ERR
, "tran property change %s/%s "
371 "failed - %s", pgName
, groupName
,
372 scf_strerror(scf_error()));
378 * Get the property handle
380 if (scf_pg_get_property(pg
, groupName
, prop
) == -1) {
381 syslog(LOG_ERR
, "get property %s/%s failed - %s",
382 pgName
, groupName
, scf_strerror(scf_error()));
388 * Value lookup is used to lookup the existing values
390 valueLookup
= scf_value_create(handle
);
391 if (valueLookup
== NULL
) {
392 syslog(LOG_ERR
, "scf value alloc for %s failed - %s",
393 pgName
, scf_strerror(scf_error()));
399 * valueIter is the iterator handle, create the resource
401 if (scf_iter_property_values(valueIter
, prop
) == -1) {
402 syslog(LOG_ERR
, "iter values for %s/%s failed - %s",
403 pgName
, groupName
, scf_strerror(scf_error()));
409 * Allocate value resource pointers.
410 * We need a value resource for each value as value pointers passed
411 * to libscf cannot be destroyed until the commit or destroy on the
412 * transaction is done.
414 * We're using GROUP_MEMBER_ALLOC initially. If it's not large
415 * enough, we'll realloc on the fly
417 valueSet
= (scf_value_t
**)calloc(1, sizeof (*valueSet
)
418 * (lastAlloc
= GROUP_MEMBER_ALLOC
));
419 if (valueSet
== NULL
) {
420 ret
= STMF_PS_ERROR_NOMEM
;
425 * Iterate through the existing values
427 while (scf_iter_next_value(valueIter
, valueLookup
) == 1) {
428 bzero(buf
, sizeof (buf
));
429 if (scf_value_get_ustring(valueLookup
, buf
, MAXNAMELEN
) == -1) {
430 syslog(LOG_ERR
, "iter %s/%s value failed - %s",
431 pgName
, groupName
, scf_strerror(scf_error()));
438 * If we're adding, it's an error
439 * If we're removing, we skip it and simply not
440 * add it to the set. Subtraction by omission.
442 if ((strlen(buf
) == strlen(memberName
)) &&
443 bcmp(buf
, memberName
, strlen(buf
)) == 0) {
444 if (addRemoveFlag
== ADD
) {
445 ret
= STMF_PS_ERROR_EXISTS
;
454 * Create the value resource for this iteration
456 valueSet
[i
] = scf_value_create(handle
);
457 if (valueSet
[i
] == NULL
) {
458 syslog(LOG_ERR
, "scf value alloc for %s failed - %s",
459 pgName
, scf_strerror(scf_error()));
467 if (scf_value_set_ustring(valueSet
[i
], buf
) == -1) {
468 syslog(LOG_ERR
, "set value for %s/%s failed - %s",
469 pgName
, groupName
, scf_strerror(scf_error()));
477 if (scf_entry_add_value(entry
, valueSet
[i
]) == -1) {
478 syslog(LOG_ERR
, "add value for %s/%s failed - %s",
479 pgName
, groupName
, scf_strerror(scf_error()));
487 * realloc if we've hit the previous alloc size
489 if (i
>= lastAlloc
) {
490 lastAlloc
+= GROUP_MEMBER_ALLOC
;
491 valueSet
= reallocarray(valueSet
, lastAlloc
,
493 if (valueSet
== NULL
) {
501 * set valueArraySize to final allocated length
502 * so we can use it to destroy the resources correctly
506 if (!found
&& (addRemoveFlag
== REMOVE
)) {
507 ret
= STMF_PS_ERROR_MEMBER_NOT_FOUND
;
510 if (ret
!= STMF_PS_SUCCESS
) {
515 * If we're adding, we have one more step. Add the member to the
518 if (addRemoveFlag
== ADD
) {
520 * Now create the new entry
522 valueSet
[i
] = scf_value_create(handle
);
523 if (valueSet
[i
] == NULL
) {
524 syslog(LOG_ERR
, "scf value alloc for %s/%s failed - %s",
525 pgName
, groupName
, scf_strerror(scf_error()));
533 * Set the new member name
535 if (scf_value_set_ustring(valueSet
[i
], memberName
) == -1) {
536 syslog(LOG_ERR
, "set value for %s/%s failed - %s",
537 pgName
, groupName
, scf_strerror(scf_error()));
545 if (scf_entry_add_value(entry
, valueSet
[i
]) == -1) {
546 syslog(LOG_ERR
, "add value for %s/%s failed - %s",
547 pgName
, groupName
, scf_strerror(scf_error()));
554 * Yes, we're finally done. We actually added or removed one entry
558 if ((commitRet
= scf_transaction_commit(tran
)) != 1) {
559 syslog(LOG_ERR
, "transaction commit for %s failed - %s",
560 pgName
, scf_strerror(scf_error()));
561 if (commitRet
== 0) {
562 ret
= STMF_PS_ERROR_BUSY
;
573 if (handle
!= NULL
) {
574 scf_handle_destroy(handle
);
577 scf_service_destroy(svc
);
583 scf_transaction_destroy(tran
);
586 scf_entry_destroy(entry
);
589 scf_property_destroy(prop
);
591 if (valueLookup
!= NULL
) {
592 scf_value_destroy(valueLookup
);
594 if (valueIter
!= NULL
) {
595 scf_iter_destroy(valueIter
);
599 * Free valueSet scf resources
601 if (valueArraySize
> 0) {
602 for (i
= 0; i
< valueArraySize
; i
++) {
603 scf_value_destroy(valueSet
[i
]);
607 * Now free the pointer array to the resources
609 if (valueSet
!= NULL
) {
617 * iPsAddRemoveLuViewEntry
619 * Adds or removes a view entry name property for a given logical unit
620 * property group. There is one logical unit property group for every logical
621 * unit that has one or more associated view entries.
623 * luPgName - Property group name of logical unit
624 * viewEntryPgName - Property group name of view entry
625 * addRemoveFlag - ADD_VE/REMOVE_VE
628 * STMF_PS_SUCCESS on success
629 * STMF_PS_ERROR_* on failure
632 iPsAddRemoveLuViewEntry(char *luPgName
, char *viewEntryPgName
,
635 scf_handle_t
*handle
= NULL
;
636 scf_service_t
*svc
= NULL
;
637 scf_propertygroup_t
*pg
= NULL
;
638 scf_property_t
*prop
= NULL
;
639 scf_value_t
*value
= NULL
;
640 scf_transaction_t
*tran
= NULL
;
641 scf_transaction_entry_t
*entry
= NULL
;
642 scf_transaction_entry_t
*entryVeName
= NULL
;
643 boolean_t createVeCnt
= B_FALSE
;
645 int ret
= STMF_PS_SUCCESS
;
648 assert(luPgName
!= NULL
|| viewEntryPgName
!= NULL
);
649 assert(!(addRemoveFlag
!= ADD
&& addRemoveFlag
!= REMOVE
));
652 * Init the service handle
654 ret
= iPsInit(&handle
, &svc
);
655 if (ret
!= STMF_PS_SUCCESS
) {
660 * Allocate scf resources
662 if (((pg
= scf_pg_create(handle
)) == NULL
) ||
663 ((tran
= scf_transaction_create(handle
)) == NULL
) ||
664 ((entry
= scf_entry_create(handle
)) == NULL
) ||
665 ((prop
= scf_property_create(handle
)) == NULL
) ||
666 ((value
= scf_value_create(handle
)) == NULL
)) {
667 syslog(LOG_ERR
, "scf alloc resource failed - %s",
668 scf_strerror(scf_error()));
673 /* get the LU property group */
674 if (scf_service_get_pg(svc
, luPgName
, pg
) == -1) {
675 if (scf_error() == SCF_ERROR_NOT_FOUND
&&
676 addRemoveFlag
== ADD
) {
677 /* if it doesn't exist, create it */
678 if (scf_service_add_pg(svc
, luPgName
,
679 SCF_GROUP_APPLICATION
, 0, pg
) == -1) {
680 syslog(LOG_ERR
, "add pg %s failed - %s",
681 luPgName
, scf_strerror(scf_error()));
684 /* we need to create the VE_CNT property */
685 createVeCnt
= B_TRUE
;
686 ret
= STMF_PS_SUCCESS
;
688 } else if (scf_error() == SCF_ERROR_NOT_FOUND
) {
689 ret
= STMF_PS_ERROR_NOT_FOUND
;
691 syslog(LOG_ERR
, "get lu pg %s failed - %s",
692 luPgName
, scf_strerror(scf_error()));
695 if (ret
!= STMF_PS_SUCCESS
) {
702 * Begin the transaction
704 if (scf_transaction_start(tran
, pg
) == -1) {
705 syslog(LOG_ERR
, "start transaction for %s failed - %s",
706 luPgName
, scf_strerror(scf_error()));
714 * Create the STMF_VE_CNT property. This will keep the current
715 * total view entries for this logical unit.
717 if (scf_transaction_property_new(tran
, entry
, STMF_VE_CNT
,
718 SCF_TYPE_COUNT
) == -1) {
719 if (scf_error() == SCF_ERROR_EXISTS
) {
720 ret
= STMF_PS_ERROR_EXISTS
;
723 "transaction property new %s/%s "
724 "failed - %s", luPgName
, STMF_VE_CNT
,
725 scf_strerror(scf_error()));
732 * The STMF_VE_CNT property already exists. Just update
735 if (scf_transaction_property_change(tran
, entry
,
736 STMF_VE_CNT
, SCF_TYPE_COUNT
) == -1) {
737 syslog(LOG_ERR
, "transaction property %s/%s change "
738 "failed - %s", luPgName
, STMF_VE_CNT
,
739 scf_strerror(scf_error()));
745 * Get the STMF_VE_CNT property
747 if (scf_pg_get_property(pg
, STMF_VE_CNT
, prop
) == -1) {
748 syslog(LOG_ERR
, "get property %s/%s failed - %s",
749 luPgName
, STMF_VE_CNT
, scf_strerror(scf_error()));
755 * Get the STMF_VE_CNT value
757 if (scf_property_get_value(prop
, value
) == -1) {
758 syslog(LOG_ERR
, "get property %s/%s value failed - %s",
759 luPgName
, STMF_VE_CNT
, scf_strerror(scf_error()));
765 * Now get the actual value from the value handle
767 if (scf_value_get_count(value
, &veCnt
) == -1) {
768 syslog(LOG_ERR
, "get count value %s/%s failed - %s",
769 luPgName
, STMF_VE_CNT
, scf_strerror(scf_error()));
775 * Reset the value resource as it is used below
777 scf_value_reset(value
);
780 if (addRemoveFlag
== ADD
) {
783 /* Check if this is the last one being removed */
786 * Delete the pg and get out if this is the last
789 if (scf_pg_delete(pg
) == -1) {
790 syslog(LOG_ERR
, "delete pg %s failed - %s",
791 luPgName
, scf_strerror(scf_error()));
803 * Set the view entry count
805 scf_value_set_count(value
, veCnt
);
808 * Add the value to the transaction entry
810 if (scf_entry_add_value(entry
, value
) == -1) {
811 syslog(LOG_ERR
, "add value %s/%s failed - %s",
812 luPgName
, STMF_VE_CNT
, scf_strerror(scf_error()));
818 * Create a transaction entry resource for the view entry name
820 entryVeName
= scf_entry_create(handle
);
821 if (entryVeName
== NULL
) {
822 syslog(LOG_ERR
, "scf transaction entry alloc %s/%s failed - %s",
823 luPgName
, viewEntryPgName
, scf_strerror(scf_error()));
828 if (addRemoveFlag
== ADD
) {
830 * If adding, create a property with the view entry name
832 if (scf_transaction_property_new(tran
, entryVeName
,
833 viewEntryPgName
, SCF_TYPE_USTRING
) == -1) {
834 if (scf_error() == SCF_ERROR_EXISTS
) {
835 ret
= STMF_PS_ERROR_EXISTS
;
838 "transaction property new %s/%s "
839 "failed - %s", luPgName
, viewEntryPgName
,
840 scf_strerror(scf_error()));
847 * If removing, delete the existing property with the view
850 if (scf_transaction_property_delete(tran
, entryVeName
,
851 viewEntryPgName
) == -1) {
852 if (scf_error() == SCF_ERROR_NOT_FOUND
) {
853 ret
= STMF_PS_ERROR_NOT_FOUND
;
856 "transaction property delete %s/%s "
857 "failed - %s", luPgName
, viewEntryPgName
,
858 scf_strerror(scf_error()));
866 * Commit property transaction
868 if ((commitRet
= scf_transaction_commit(tran
)) != 1) {
869 syslog(LOG_ERR
, "transaction commit for %s failed - %s",
870 luPgName
, scf_strerror(scf_error()));
871 if (commitRet
== 0) {
872 ret
= STMF_PS_ERROR_BUSY
;
883 if (handle
!= NULL
) {
884 scf_handle_destroy(handle
);
887 scf_service_destroy(svc
);
893 scf_transaction_destroy(tran
);
896 scf_entry_destroy(entry
);
898 if (entryVeName
!= NULL
) {
899 scf_entry_destroy(entryVeName
);
902 scf_property_destroy(prop
);
905 scf_value_destroy(value
);
914 * Add a view entry property group and optionally, a logical unit property
915 * group if it does not exist.
917 * luName - ascii hexadecimal logical unit identifier
918 * viewEntryName - name of view entry (VIEW_ENTRY_nn)
919 * viewEntry - pointer to stmfViewEntry structure
922 iPsAddViewEntry(char *luPgName
, char *viewEntryPgName
, stmfViewEntry
*viewEntry
)
924 scf_handle_t
*handle
= NULL
;
925 scf_service_t
*svc
= NULL
;
926 scf_propertygroup_t
*pg
= NULL
;
927 scf_value_t
*value
[VIEW_ENTRY_STRUCT_CNT
];
928 scf_transaction_t
*tran
= NULL
;
929 scf_transaction_entry_t
*entry
[VIEW_ENTRY_STRUCT_CNT
];
934 boolean_t createdVePg
= B_FALSE
;
938 assert(luPgName
!= NULL
|| viewEntryPgName
!= NULL
||
941 bzero(value
, sizeof (value
));
942 bzero(entry
, sizeof (entry
));
945 * Init the service handle
947 ret
= iPsInit(&handle
, &svc
);
948 if (ret
!= STMF_PS_SUCCESS
) {
953 * Allocate scf resources
955 if (((pg
= scf_pg_create(handle
)) == NULL
) ||
956 ((tran
= scf_transaction_create(handle
)) == NULL
)) {
957 syslog(LOG_ERR
, "scf alloc resource failed - %s",
958 scf_strerror(scf_error()));
964 * allocate value and entry resources for scf
966 for (i
= 0; i
< VIEW_ENTRY_STRUCT_CNT
; i
++) {
967 if (((value
[i
] = scf_value_create(handle
)) == NULL
) ||
968 ((entry
[i
] = scf_entry_create(handle
)) == NULL
)) {
969 syslog(LOG_ERR
, "scf alloc resource failed - %s",
970 scf_strerror(scf_error()));
979 * Create the View Entry property group
981 if (scf_service_add_pg(svc
, viewEntryPgName
, SCF_GROUP_APPLICATION
,
983 if (scf_error() == SCF_ERROR_EXISTS
) {
984 ret
= STMF_PS_ERROR_EXISTS
;
986 syslog(LOG_ERR
, "add pg %s failed - %s",
987 viewEntryPgName
, scf_strerror(scf_error()));
993 createdVePg
= B_TRUE
;
996 * Add the view entry as properties on the view entry group
1000 * Begin property update transaction
1002 if (scf_transaction_start(tran
, pg
) == -1) {
1003 syslog(LOG_ERR
, "start transaction for add %s failed - %s",
1004 viewEntryPgName
, scf_strerror(scf_error()));
1005 ret
= STMF_PS_ERROR
;
1010 * Add allHosts property
1012 if (scf_transaction_property_new(tran
, entry
[i
],
1013 STMF_VE_ALLHOSTS
, SCF_TYPE_BOOLEAN
) == -1) {
1014 if (scf_error() == SCF_ERROR_EXISTS
) {
1015 ret
= STMF_PS_ERROR_EXISTS
;
1017 syslog(LOG_ERR
, "transaction property new %s/%s "
1018 "failed - %s", viewEntryPgName
, STMF_VE_ALLHOSTS
,
1019 scf_strerror(scf_error()));
1020 ret
= STMF_PS_ERROR
;
1025 /* Set the allHosts value */
1026 scfBool
= viewEntry
->allHosts
;
1027 scf_value_set_boolean(value
[i
], scfBool
);
1030 * Add the allHosts value to the transaction
1032 if (scf_entry_add_value(entry
[i
], value
[i
]) == -1) {
1033 syslog(LOG_ERR
, "add value %s/%s failed - %s",
1034 viewEntryPgName
, STMF_VE_ALLHOSTS
,
1035 scf_strerror(scf_error()));
1036 ret
= STMF_PS_ERROR
;
1043 * Create hostGroup property
1045 if (scf_transaction_property_new(tran
, entry
[i
],
1046 STMF_VE_HOSTGROUP
, SCF_TYPE_USTRING
) == -1) {
1047 if (scf_error() == SCF_ERROR_EXISTS
) {
1048 ret
= STMF_PS_ERROR_EXISTS
;
1050 syslog(LOG_ERR
, "transaction property new %s/%s "
1051 "failed - %s", viewEntryPgName
, STMF_VE_HOSTGROUP
,
1052 scf_strerror(scf_error()));
1053 ret
= STMF_PS_ERROR
;
1059 * Set the value for hostGroup
1061 if (scf_value_set_ustring(value
[i
], viewEntry
->hostGroup
) == -1) {
1062 syslog(LOG_ERR
, "set value %s/%s failed - %s",
1063 viewEntryPgName
, STMF_VE_HOSTGROUP
,
1064 scf_strerror(scf_error()));
1065 ret
= STMF_PS_ERROR
;
1070 * Add the hostGroup value to the transaction entry
1072 if (scf_entry_add_value(entry
[i
], value
[i
]) == -1) {
1073 syslog(LOG_ERR
, "add value %s/%s failed - %s",
1074 viewEntryPgName
, STMF_VE_HOSTGROUP
,
1075 scf_strerror(scf_error()));
1076 ret
= STMF_PS_ERROR
;
1083 * Create the allTargets property
1085 if (scf_transaction_property_new(tran
, entry
[i
],
1086 STMF_VE_ALLTARGETS
, SCF_TYPE_BOOLEAN
) == -1) {
1087 if (scf_error() == SCF_ERROR_EXISTS
) {
1088 ret
= STMF_PS_ERROR_EXISTS
;
1090 syslog(LOG_ERR
, "transaction property new %s/%s "
1091 "failed - %s", viewEntryPgName
, STMF_VE_ALLTARGETS
,
1092 scf_strerror(scf_error()));
1093 ret
= STMF_PS_ERROR
;
1099 * Set the allTargets value
1101 scfBool
= viewEntry
->allTargets
;
1102 scf_value_set_boolean(value
[i
], scfBool
);
1105 * Add the allTargets value to the transaction
1107 if (scf_entry_add_value(entry
[i
], value
[i
]) == -1) {
1108 syslog(LOG_ERR
, "add value %s/%s failed - %s",
1109 viewEntryPgName
, STMF_VE_ALLTARGETS
,
1110 scf_strerror(scf_error()));
1111 ret
= STMF_PS_ERROR
;
1118 * Create targetGroup property
1120 if (scf_transaction_property_new(tran
, entry
[i
],
1121 STMF_VE_TARGETGROUP
, SCF_TYPE_USTRING
) == -1) {
1122 if (scf_error() == SCF_ERROR_EXISTS
) {
1123 ret
= STMF_PS_ERROR_EXISTS
;
1125 syslog(LOG_ERR
, "transaction property new %s/%s "
1126 "failed - %s", viewEntryPgName
,
1127 STMF_VE_TARGETGROUP
, scf_strerror(scf_error()));
1128 ret
= STMF_PS_ERROR
;
1134 * Set the value for targetGroup
1136 if (scf_value_set_ustring(value
[i
], viewEntry
->targetGroup
) == -1) {
1137 syslog(LOG_ERR
, "set value %s/%s failed - %s",
1138 viewEntryPgName
, STMF_VE_TARGETGROUP
,
1139 scf_strerror(scf_error()));
1140 ret
= STMF_PS_ERROR
;
1145 * Add targetGroup value to the transaction
1147 if (scf_entry_add_value(entry
[i
], value
[i
]) == -1) {
1148 syslog(LOG_ERR
, "add value %s/%s failed - %s",
1149 viewEntryPgName
, STMF_VE_TARGETGROUP
,
1150 scf_strerror(scf_error()));
1151 ret
= STMF_PS_ERROR
;
1158 * Create the luNbr property
1160 if (scf_transaction_property_new(tran
, entry
[i
], STMF_VE_LUNBR
,
1161 SCF_TYPE_OPAQUE
) == -1) {
1162 if (scf_error() == SCF_ERROR_EXISTS
) {
1163 ret
= STMF_PS_ERROR_EXISTS
;
1165 syslog(LOG_ERR
, "transaction property new %s/%s "
1166 "failed - %s", viewEntryPgName
, STMF_VE_LUNBR
,
1167 scf_strerror(scf_error()));
1168 ret
= STMF_PS_ERROR
;
1176 if (scf_value_set_opaque(value
[i
], (char *)viewEntry
->luNbr
,
1177 sizeof (viewEntry
->luNbr
)) == -1) {
1178 syslog(LOG_ERR
, "set value %s/%s failed - %s",
1179 viewEntryPgName
, STMF_VE_LUNBR
, scf_strerror(scf_error()));
1180 ret
= STMF_PS_ERROR
;
1185 * Add luNbr to the transaction entry
1187 if (scf_entry_add_value(entry
[i
], value
[i
]) == -1) {
1188 syslog(LOG_ERR
, "add value %s/%s failed - %s",
1189 viewEntryPgName
, STMF_VE_LUNBR
, scf_strerror(scf_error()));
1190 ret
= STMF_PS_ERROR
;
1195 * Now that we've successfully added the view entry,
1196 * update the logical unit property group or create
1197 * it if it does not exist
1199 ret
= iPsAddRemoveLuViewEntry(luPgName
, viewEntryPgName
, ADD
);
1202 * If we did not add the view entry name to the logical unit,
1203 * make sure we do not commit the transaction
1205 if (ret
!= STMF_PS_SUCCESS
) {
1210 * Commit property transaction
1212 if ((commitRet
= scf_transaction_commit(tran
)) != 1) {
1213 syslog(LOG_ERR
, "transaction commit for add %s failed - %s",
1214 viewEntryPgName
, scf_strerror(scf_error()));
1215 if (commitRet
== 0) {
1216 ret
= STMF_PS_ERROR_BUSY
;
1218 ret
= STMF_PS_ERROR
;
1222 if (ret
!= STMF_PS_SUCCESS
) {
1224 * If we did not commit, try to remove the view entry name
1225 * from the logical unit.
1226 * If that fails, we're now inconsistent.
1228 backoutRet
= iPsAddRemoveLuViewEntry(luPgName
, viewEntryPgName
,
1231 if (backoutRet
!= STMF_PS_SUCCESS
) {
1232 syslog(LOG_ERR
, "remove lu view entry %s failed"
1233 "possible inconsistency - %s", luPgName
,
1234 scf_strerror(scf_error()));
1237 * We are still in an error scenario even though the remove
1238 * lu view entry succeeded.
1247 if (handle
!= NULL
) {
1248 scf_handle_destroy(handle
);
1251 scf_service_destroy(svc
);
1253 /* if there was an error, delete the created pg if one was created */
1254 if ((ret
!= STMF_PS_SUCCESS
) && createdVePg
) {
1255 if (scf_pg_delete(pg
) == -1) {
1256 syslog(LOG_ERR
, "delete VE pg %s failed - %s",
1257 viewEntryPgName
, scf_strerror(scf_error()));
1264 scf_transaction_destroy(tran
);
1267 * Free value and entry scf resources
1270 for (j
= 0; j
< VIEW_ENTRY_STRUCT_CNT
; j
++) {
1271 if (value
[j
] != NULL
)
1272 scf_value_destroy(value
[j
]);
1273 if (entry
[j
] != NULL
)
1274 scf_entry_destroy(entry
[j
]);
1281 * psClearProviderData
1283 * providerName - name of provider data to clear
1286 psClearProviderData(char *providerName
, int providerType
)
1288 scf_handle_t
*handle
= NULL
;
1289 scf_service_t
*svc
= NULL
;
1290 scf_propertygroup_t
*pg
= NULL
;
1291 char pgName
[MAXPATHLEN
];
1292 int ret
= STMF_PS_SUCCESS
;
1293 boolean_t pgNotFound
= B_FALSE
;
1295 if (providerName
== NULL
|| (providerType
!= STMF_LU_PROVIDER_TYPE
&&
1296 providerType
!= STMF_PORT_PROVIDER_TYPE
)) {
1297 ret
= STMF_PS_ERROR_INVALID_ARG
;
1301 ret
= iPsInit(&handle
, &svc
);
1302 if (ret
!= STMF_PS_SUCCESS
) {
1307 * Allocate scf resources
1309 if ((pg
= scf_pg_create(handle
)) == NULL
) {
1310 syslog(LOG_ERR
, "scf alloc resource failed - %s",
1311 scf_strerror(scf_error()));
1312 ret
= STMF_PS_ERROR
;
1317 * create the property group name
1319 (void) snprintf(pgName
, sizeof (pgName
), "%s%s",
1320 STMF_PROVIDER_DATA_PREFIX
, providerName
);
1323 * delete provider property group
1325 if (scf_service_get_pg(svc
, pgName
, pg
) == -1) {
1326 if (scf_error() != SCF_ERROR_NOT_FOUND
) {
1327 syslog(LOG_ERR
, "get pg %s failed - %s",
1328 pgName
, scf_strerror(scf_error()));
1329 ret
= STMF_PS_ERROR
;
1332 pgNotFound
= B_TRUE
;
1336 if (!pgNotFound
&& (scf_pg_delete(pg
) == -1)) {
1337 syslog(LOG_ERR
, "delete pg %s failed - %s",
1338 pgName
, scf_strerror(scf_error()));
1339 ret
= STMF_PS_ERROR
;
1344 ret
= STMF_PS_ERROR_NOT_FOUND
;
1351 if (handle
!= NULL
) {
1352 scf_handle_destroy(handle
);
1355 scf_service_destroy(svc
);
1365 * iPsCreateDeleteGroup
1367 * Creates or deletes a group (target or host)
1369 * When creating a group, two properties are created. One to hold the group
1370 * name and the other to hold the group members.
1372 * pgName - Property group name
1373 * groupName - group name to create
1374 * addRemoveFlag - ADD_GROUP/REMOVE_GROUP
1377 * STMF_PS_SUCCESS on success
1378 * STMF_PS_ERROR_* on failure
1381 iPsCreateDeleteGroup(char *pgRefName
, char *groupName
, int addRemoveFlag
)
1383 scf_handle_t
*handle
= NULL
;
1384 scf_service_t
*svc
= NULL
;
1385 scf_propertygroup_t
*pg
= NULL
;
1386 scf_property_t
*prop
= NULL
;
1387 scf_iter_t
*propIter
= NULL
;
1388 scf_transaction_t
*tran
= NULL
;
1389 scf_transaction_entry_t
*entry1
= NULL
;
1390 scf_transaction_entry_t
*entry2
= NULL
;
1391 scf_value_t
*value
= NULL
;
1393 char buf1
[MAXNAMELEN
];
1394 char buf2
[MAXNAMELEN
];
1395 char tmpbuf
[MAXNAMELEN
];
1396 boolean_t found
= B_FALSE
;
1397 int ret
= STMF_PS_SUCCESS
;
1400 assert(groupName
!= NULL
);
1402 ret
= iPsInit(&handle
, &svc
);
1403 if (ret
!= STMF_PS_SUCCESS
) {
1408 * Allocate scf resources
1410 if (((pg
= scf_pg_create(handle
)) == NULL
) ||
1411 ((tran
= scf_transaction_create(handle
)) == NULL
) ||
1412 ((entry1
= scf_entry_create(handle
)) == NULL
) ||
1413 ((entry2
= scf_entry_create(handle
)) == NULL
) ||
1414 ((prop
= scf_property_create(handle
)) == NULL
) ||
1415 ((propIter
= scf_iter_create(handle
)) == NULL
) ||
1416 ((value
= scf_value_create(handle
)) == NULL
)) {
1417 syslog(LOG_ERR
, "scf alloc resource failed - %s",
1418 scf_strerror(scf_error()));
1419 ret
= STMF_PS_ERROR
;
1424 * Get the property group being modified
1426 if (scf_service_get_pg(svc
, pgRefName
, pg
) == -1) {
1427 if (scf_error() == SCF_ERROR_NOT_FOUND
&&
1428 addRemoveFlag
== ADD
) {
1429 if (scf_service_add_pg(svc
, pgRefName
,
1430 SCF_GROUP_APPLICATION
, 0, pg
) == -1) {
1431 syslog(LOG_ERR
, "add pg %s failed - %s",
1432 pgRefName
, scf_strerror(scf_error()));
1433 ret
= STMF_PS_ERROR
;
1435 } else if (scf_error() == SCF_ERROR_NOT_FOUND
) {
1436 syslog(LOG_ERR
, "get pg %s failed - %s",
1437 pgRefName
, scf_strerror(scf_error()));
1438 ret
= STMF_PS_ERROR_NOT_FOUND
;
1440 syslog(LOG_ERR
, "get pg %s failed - %s",
1441 pgRefName
, scf_strerror(scf_error()));
1442 ret
= STMF_PS_ERROR
;
1444 if (ret
!= STMF_PS_SUCCESS
) {
1450 * propIter is the iterator handle
1452 if (scf_iter_pg_properties(propIter
, pg
) == -1) {
1453 syslog(LOG_ERR
, "iter properties for %s failed - %s",
1454 pgRefName
, scf_strerror(scf_error()));
1455 ret
= STMF_PS_ERROR
;
1460 * Iterate through the group names.
1461 * If we find it in the list, it's an error when addRemoveFlag == ADD.
1463 while (scf_iter_next_property(propIter
, prop
) == 1) {
1464 if (scf_property_get_name(prop
, buf1
, sizeof (buf1
)) == -1) {
1465 syslog(LOG_ERR
, "get name from %s iter failed - %s",
1466 pgRefName
, scf_strerror(scf_error()));
1467 ret
= STMF_PS_ERROR
;
1471 * Skip over member list properties
1473 if (strstr(buf1
, STMF_MEMBER_LIST_SUFFIX
)) {
1476 if (scf_property_get_value(prop
, value
) == -1) {
1477 syslog(LOG_ERR
, "get property value %s/%s failed - %s",
1478 pgRefName
, buf1
, scf_strerror(scf_error()));
1479 ret
= STMF_PS_ERROR
;
1482 if (scf_value_get_ustring(value
, tmpbuf
,
1483 sizeof (tmpbuf
)) == -1) {
1484 syslog(LOG_ERR
, "get ustring %s/%s failed - %s",
1485 pgRefName
, buf1
, scf_strerror(scf_error()));
1486 ret
= STMF_PS_ERROR
;
1490 if ((strlen(tmpbuf
) == strlen(groupName
)) &&
1491 bcmp(tmpbuf
, groupName
, strlen(tmpbuf
)) == 0) {
1492 if (addRemoveFlag
== ADD
) {
1493 ret
= STMF_PS_ERROR_EXISTS
;
1497 * buf1 contains the name for REMOVE
1503 if (ret
!= STMF_PS_SUCCESS
) {
1507 scf_value_reset(value
);
1509 if (!found
&& addRemoveFlag
== REMOVE
) {
1510 ret
= STMF_PS_ERROR_NOT_FOUND
;
1515 * If we're adding, we need to create a new property name for the
1518 if (addRemoveFlag
== ADD
) {
1519 for (groupIdx
= 0; groupIdx
< GROUP_MAX
; groupIdx
++) {
1520 if (snprintf(buf1
, sizeof (buf1
), "%s-%lld",
1521 STMF_GROUP_PREFIX
, groupIdx
) > sizeof (buf1
)) {
1523 "buffer overflow on property name %s",
1525 ret
= STMF_PS_ERROR
;
1528 if (scf_pg_get_property(pg
, buf1
, prop
) == -1) {
1529 if (scf_error() != SCF_ERROR_NOT_FOUND
) {
1530 syslog(LOG_ERR
, "get property %s/%s "
1531 "failed - %s", pgRefName
, buf1
,
1532 scf_strerror(scf_error()));
1533 ret
= STMF_PS_ERROR
;
1541 * Now create the new member list property for the new group
1543 if (snprintf(buf2
, sizeof (buf2
), "%s-%s", buf1
,
1544 STMF_MEMBER_LIST_SUFFIX
) > sizeof (buf2
)) {
1545 syslog(LOG_ERR
, "buffer overflow on property name %s",
1547 ret
= STMF_PS_ERROR
;
1552 * buf1 now contains the name of the property if it was found in the
1553 * list in the case of delete or the next available property name
1554 * in the case of create
1556 * buf2 now contains the member list property name
1558 if (scf_transaction_start(tran
, pg
) == -1) {
1559 syslog(LOG_ERR
, "start transaction for %s failed - %s",
1560 pgRefName
, scf_strerror(scf_error()));
1561 ret
= STMF_PS_ERROR
;
1565 if (addRemoveFlag
== ADD
) {
1567 * Create the property 'group name'
1568 * This is the container for the group name
1570 if (scf_transaction_property_new(tran
, entry1
, buf1
,
1571 SCF_TYPE_USTRING
) == -1) {
1572 syslog(LOG_ERR
, "transaction property new %s/%s "
1573 "failed - %s", pgRefName
, buf1
,
1574 scf_strerror(scf_error()));
1575 ret
= STMF_PS_ERROR
;
1578 if (scf_value_set_ustring(value
, groupName
) == -1) {
1579 syslog(LOG_ERR
, "set ustring %s/%s failed - %s",
1580 pgRefName
, buf1
, scf_strerror(scf_error()));
1581 ret
= STMF_PS_ERROR
;
1584 if (scf_entry_add_value(entry1
, value
) == -1) {
1585 syslog(LOG_ERR
, "add value %s/%s failed - %s",
1586 pgRefName
, buf1
, scf_strerror(scf_error()));
1587 ret
= STMF_PS_ERROR
;
1591 * Create the property 'group list'
1592 * This is the container for the group members
1594 if (scf_transaction_property_new(tran
, entry2
, buf2
,
1595 SCF_TYPE_USTRING
) == -1) {
1596 syslog(LOG_ERR
, "transaction property new %s/%s "
1597 "failed - %s", pgRefName
, buf2
,
1598 scf_strerror(scf_error()));
1599 ret
= STMF_PS_ERROR
;
1604 * Delete the property 'group name'
1606 if (scf_transaction_property_delete(tran
, entry1
, buf1
)
1609 "transaction property delete %s/%s failed - %s",
1610 pgRefName
, buf1
, scf_strerror(scf_error()));
1611 ret
= STMF_PS_ERROR
;
1615 * Delete the property 'group list'
1617 if (scf_transaction_property_delete(tran
, entry2
, buf2
)
1619 syslog(LOG_ERR
, "transaction property delete %s/%s "
1620 "failed - %s", pgRefName
, buf2
,
1621 scf_strerror(scf_error()));
1622 ret
= STMF_PS_ERROR
;
1627 if (ret
!= STMF_PS_SUCCESS
) {
1631 if ((commitRet
= scf_transaction_commit(tran
)) != 1) {
1632 syslog(LOG_ERR
, "transaction commit for %s failed - %s",
1633 pgRefName
, scf_strerror(scf_error()));
1634 if (commitRet
== 0) {
1635 ret
= STMF_PS_ERROR_BUSY
;
1637 ret
= STMF_PS_ERROR
;
1645 if (handle
!= NULL
) {
1646 scf_handle_destroy(handle
);
1649 scf_service_destroy(svc
);
1655 scf_transaction_destroy(tran
);
1657 if (entry1
!= NULL
) {
1658 scf_entry_destroy(entry1
);
1660 if (entry2
!= NULL
) {
1661 scf_entry_destroy(entry2
);
1664 scf_property_destroy(prop
);
1666 if (propIter
!= NULL
) {
1667 scf_iter_destroy(propIter
);
1669 if (value
!= NULL
) {
1670 scf_value_destroy(value
);
1679 * pgName - Property group name
1680 * groupList - pointer to pointer to stmfGroupList structure. On success,
1681 * contains the list of groups
1684 * STMF_PS_SUCCESS on success
1685 * STMF_PS_ERROR_* on failure
1688 iPsGetGroupList(char *pgName
, stmfGroupList
**groupList
)
1690 scf_handle_t
*handle
= NULL
;
1691 scf_service_t
*svc
= NULL
;
1692 scf_propertygroup_t
*pg
= NULL
;
1693 scf_property_t
*prop
= NULL
;
1694 scf_iter_t
*propIter
= NULL
;
1695 scf_value_t
*value
= NULL
;
1696 char buf
[MAXNAMELEN
];
1699 int ret
= STMF_PS_SUCCESS
;
1701 assert(groupList
!= NULL
);
1703 ret
= iPsInit(&handle
, &svc
);
1704 if (ret
!= STMF_PS_SUCCESS
) {
1709 * Allocate scf resources
1711 if (((pg
= scf_pg_create(handle
)) == NULL
) ||
1712 ((prop
= scf_property_create(handle
)) == NULL
) ||
1713 ((propIter
= scf_iter_create(handle
)) == NULL
) ||
1714 ((value
= scf_value_create(handle
)) == NULL
)) {
1715 syslog(LOG_ERR
, "scf alloc resource failed - %s",
1716 scf_strerror(scf_error()));
1717 ret
= STMF_PS_ERROR
;
1721 if (scf_service_get_pg(svc
, pgName
, pg
) == -1) {
1722 if (scf_error() == SCF_ERROR_NOT_FOUND
) {
1723 syslog(LOG_ERR
, "get pg %s failed - %s",
1724 pgName
, scf_strerror(scf_error()));
1725 ret
= STMF_PS_ERROR_NOT_FOUND
;
1727 syslog(LOG_ERR
, "get pg %s failed - %s",
1728 pgName
, scf_strerror(scf_error()));
1729 ret
= STMF_PS_ERROR
;
1735 * propIter is the iterator handle
1737 if (scf_iter_pg_properties(propIter
, pg
) == -1) {
1738 syslog(LOG_ERR
, "iter properties for %s failed - %s",
1739 pgName
, scf_strerror(scf_error()));
1740 ret
= STMF_PS_ERROR
;
1744 while (scf_iter_next_property(propIter
, prop
) == 1) {
1745 if (scf_property_get_name(prop
, buf
, sizeof (buf
)) == -1) {
1746 syslog(LOG_ERR
, "get name from %s iter failed - %s",
1747 pgName
, scf_strerror(scf_error()));
1748 ret
= STMF_PS_ERROR
;
1752 * Skip over member list properties
1754 if (strstr(buf
, STMF_MEMBER_LIST_SUFFIX
)) {
1761 * propIter is the iterator handle
1763 if (scf_iter_pg_properties(propIter
, pg
) == -1) {
1764 syslog(LOG_ERR
, "iter properties for %s failed - %s",
1765 pgName
, scf_strerror(scf_error()));
1766 ret
= STMF_PS_ERROR
;
1770 *groupList
= (stmfGroupList
*)calloc(1, sizeof (stmfGroupList
) +
1771 memberCnt
* sizeof (stmfGroupName
));
1773 if (*groupList
== NULL
) {
1774 ret
= STMF_PS_ERROR_NOMEM
;
1779 * In order to get a list of groups, simply get all of the
1780 * properties that are not member list properties, i.e. the group
1782 * It's possible for this list to grow beyond what was originally
1783 * read so just ensure we're not writing beyond our allocated buffer
1784 * by ensuring i < memberCnt
1786 while ((scf_iter_next_property(propIter
, prop
) == 1) &&
1788 if (scf_property_get_name(prop
, buf
, sizeof (buf
)) == -1) {
1789 syslog(LOG_ERR
, "get name from %s iter failed - %s",
1790 pgName
, scf_strerror(scf_error()));
1791 ret
= STMF_PS_ERROR
;
1795 * Skip over member list properties
1797 if (strstr(buf
, STMF_MEMBER_LIST_SUFFIX
)) {
1800 if (scf_property_get_value(prop
, value
) == -1) {
1801 syslog(LOG_ERR
, "get property value %s/%s failed - %s",
1802 pgName
, buf
, scf_strerror(scf_error()));
1803 ret
= STMF_PS_ERROR
;
1806 if (scf_value_get_ustring(value
, buf
, sizeof (buf
)) == -1) {
1807 syslog(LOG_ERR
, "get ustring %s/%s failed - %s",
1808 pgName
, buf
, scf_strerror(scf_error()));
1809 ret
= STMF_PS_ERROR
;
1812 bcopy(buf
, (*groupList
)->name
[i
++], strlen(buf
));
1813 (*groupList
)->cnt
++;
1816 if (ret
!= STMF_PS_SUCCESS
) {
1825 if (handle
!= NULL
) {
1826 scf_handle_destroy(handle
);
1829 scf_service_destroy(svc
);
1834 if (propIter
!= NULL
) {
1835 scf_iter_destroy(propIter
);
1838 scf_property_destroy(prop
);
1840 if (value
!= NULL
) {
1841 scf_value_destroy(value
);
1848 * iPsGetGroupMemberList
1850 * pgName - Property group name
1851 * groupName - group name (host group or target group)
1852 * groupMemberList - pointer to pointer to stmfGroupProperties structure. On
1853 * success, contains the list of group members
1856 * STMF_PS_SUCCESS on success
1857 * STMF_PS_ERROR_* on failure
1860 iPsGetGroupMemberList(char *pgName
, char *groupName
,
1861 stmfGroupProperties
**groupMemberList
)
1863 scf_handle_t
*handle
= NULL
;
1864 scf_service_t
*svc
= NULL
;
1865 scf_propertygroup_t
*pg
= NULL
;
1866 scf_property_t
*prop
= NULL
;
1867 scf_value_t
*valueLookup
= NULL
;
1868 scf_iter_t
*valueIter
= NULL
;
1872 int ret
= STMF_PS_SUCCESS
;
1873 char buf
[MAXNAMELEN
];
1875 assert(pgName
!= NULL
&& groupName
!= NULL
);
1878 * init the service handle
1880 ret
= iPsInit(&handle
, &svc
);
1881 if (ret
!= STMF_PS_SUCCESS
) {
1886 * Allocate scf resources
1888 if (((pg
= scf_pg_create(handle
)) == NULL
) ||
1889 ((prop
= scf_property_create(handle
)) == NULL
) ||
1890 ((valueIter
= scf_iter_create(handle
)) == NULL
) ||
1891 ((valueLookup
= scf_value_create(handle
)) == NULL
)) {
1892 syslog(LOG_ERR
, "scf alloc resource failed - %s",
1893 scf_strerror(scf_error()));
1894 ret
= STMF_PS_ERROR
;
1899 * get the service property group handle
1901 if (scf_service_get_pg(svc
, pgName
, pg
) == -1) {
1902 if (scf_error() == SCF_ERROR_NOT_FOUND
) {
1903 ret
= STMF_PS_ERROR_NOT_FOUND
;
1905 ret
= STMF_PS_ERROR
;
1907 syslog(LOG_ERR
, "get pg %s failed - %s",
1908 pgName
, scf_strerror(scf_error()));
1913 * Get the property handle
1914 * based on the target or host group name
1916 if (scf_pg_get_property(pg
, groupName
, prop
) == -1) {
1917 syslog(LOG_ERR
, "get property %s/%s failed - %s",
1918 pgName
, groupName
, scf_strerror(scf_error()));
1919 ret
= STMF_PS_ERROR
;
1924 * valueIter is the iterator handle
1926 if (scf_iter_property_values(valueIter
, prop
) == -1) {
1927 syslog(LOG_ERR
, "iter value %s/%s failed - %s",
1928 pgName
, groupName
, scf_strerror(scf_error()));
1929 ret
= STMF_PS_ERROR
;
1933 while (scf_iter_next_value(valueIter
, valueLookup
) == 1) {
1934 if (scf_value_get_ustring(valueLookup
, buf
, MAXNAMELEN
) == -1) {
1935 syslog(LOG_ERR
, "iter value %s/%s failed - %s",
1936 pgName
, groupName
, scf_strerror(scf_error()));
1937 ret
= STMF_PS_ERROR
;
1944 * valueIter is the iterator handle
1946 if (scf_iter_property_values(valueIter
, prop
) == -1) {
1947 syslog(LOG_ERR
, "iter value %s/%s failed - %s",
1948 pgName
, groupName
, scf_strerror(scf_error()));
1949 ret
= STMF_PS_ERROR
;
1955 *groupMemberList
= (stmfGroupProperties
*)calloc(1,
1956 sizeof (stmfGroupProperties
) + memberCnt
* sizeof (stmfDevid
));
1957 if (*groupMemberList
== NULL
) {
1958 ret
= STMF_PS_ERROR_NOMEM
;
1963 while ((scf_iter_next_value(valueIter
, valueLookup
) == 1) &&
1965 if ((len
= scf_value_get_ustring(valueLookup
, buf
, MAXNAMELEN
))
1967 syslog(LOG_ERR
, "iter value %s/%s failed - %s",
1968 pgName
, groupName
, scf_strerror(scf_error()));
1969 ret
= STMF_PS_ERROR
;
1972 if (len
< sizeof (stmfDevid
) - 1) {
1973 (*groupMemberList
)->name
[i
].identLength
= len
;
1975 (*groupMemberList
)->name
[i
++].ident
, len
);
1976 (*groupMemberList
)->cnt
++;
1978 ret
= STMF_PS_ERROR
;
1983 if (ret
!= STMF_PS_SUCCESS
) {
1984 free(*groupMemberList
);
1992 if (handle
!= NULL
) {
1993 scf_handle_destroy(handle
);
1996 scf_service_destroy(svc
);
2002 scf_property_destroy(prop
);
2004 if (valueLookup
!= NULL
) {
2005 scf_value_destroy(valueLookup
);
2007 if (valueIter
!= NULL
) {
2008 scf_iter_destroy(valueIter
);
2015 psGetServicePersist(uint8_t *persistType
)
2017 scf_handle_t
*handle
= NULL
;
2018 scf_service_t
*svc
= NULL
;
2022 ret
= iPsInit(&handle
, &svc
);
2023 if (ret
!= STMF_PS_SUCCESS
) {
2024 return (STMF_PS_ERROR
);
2027 ret
= iPsGetSetPersistType(persistType
, handle
, svc
, GET
);
2032 if (handle
!= NULL
) {
2033 scf_handle_destroy(handle
);
2036 scf_service_destroy(svc
);
2042 psSetServicePersist(uint8_t persistType
)
2044 scf_handle_t
*handle
= NULL
;
2045 scf_service_t
*svc
= NULL
;
2049 ret
= iPsInit(&handle
, &svc
);
2050 if (ret
!= STMF_PS_SUCCESS
) {
2051 return (STMF_PS_ERROR
);
2054 ret
= iPsGetSetPersistType(&persistType
, handle
, svc
, SET
);
2059 if (handle
!= NULL
) {
2060 scf_handle_destroy(handle
);
2063 scf_service_destroy(svc
);
2069 iPsGetSetPersistType(uint8_t *persistType
, scf_handle_t
*handle
,
2070 scf_service_t
*svc
, int getSet
)
2072 scf_propertygroup_t
*pg
= NULL
;
2073 scf_property_t
*prop
= NULL
;
2074 scf_value_t
*value
= NULL
;
2075 scf_transaction_t
*tran
= NULL
;
2076 scf_transaction_entry_t
*entry
= NULL
;
2077 char iPersistTypeGet
[MAXNAMELEN
] = {0};
2079 int ret
= STMF_PS_SUCCESS
;
2082 if (((pg
= scf_pg_create(handle
)) == NULL
) ||
2083 ((prop
= scf_property_create(handle
)) == NULL
) ||
2084 ((entry
= scf_entry_create(handle
)) == NULL
) ||
2085 ((tran
= scf_transaction_create(handle
)) == NULL
) ||
2086 ((value
= scf_value_create(handle
)) == NULL
)) {
2087 syslog(LOG_ERR
, "scf alloc resource failed - %s",
2088 scf_strerror(scf_error()));
2089 ret
= STMF_PS_ERROR
;
2093 if (getSet
== GET
) {
2094 /* set to default */
2095 *persistType
= STMF_PERSIST_SMF
;
2096 iPersistType
= STMF_PS_PERSIST_SMF
;
2099 if (getSet
== SET
) {
2100 if (*persistType
== STMF_PERSIST_SMF
) {
2101 iPersistType
= STMF_PS_PERSIST_SMF
;
2102 } else if (*persistType
== STMF_PERSIST_NONE
) {
2103 iPersistType
= STMF_PS_PERSIST_NONE
;
2105 ret
= STMF_PS_ERROR
;
2111 * get stmf data property group
2113 if (scf_service_get_pg(svc
, STMF_DATA_GROUP
, pg
) == -1) {
2114 if (scf_error() == SCF_ERROR_NOT_FOUND
) {
2115 ret
= STMF_PS_ERROR_NOT_FOUND
;
2117 ret
= STMF_PS_ERROR
;
2119 syslog(LOG_ERR
, "get pg %s failed - %s",
2120 STMF_DATA_GROUP
, scf_strerror(scf_error()));
2125 /* find persistence property */
2127 * Get the persistence property
2129 if (scf_pg_get_property(pg
, STMF_PERSIST_TYPE
, prop
) == -1) {
2130 if (scf_error() == SCF_ERROR_NOT_FOUND
) {
2131 ret
= STMF_PS_ERROR_NOT_FOUND
;
2133 syslog(LOG_ERR
, "get property %s/%s failed - %s",
2134 STMF_DATA_GROUP
, STMF_PERSIST_TYPE
,
2135 scf_strerror(scf_error()));
2136 ret
= STMF_PS_ERROR
;
2141 /* no persist property found */
2142 if (ret
== STMF_PS_ERROR_NOT_FOUND
|| getSet
== SET
) {
2144 * If we have no persistType property, go ahead
2145 * and create it with the user specified value or
2146 * the default value.
2149 * Begin the transaction
2151 if (scf_transaction_start(tran
, pg
) == -1) {
2152 syslog(LOG_ERR
, "start transaction for %s failed - %s",
2153 STMF_DATA_GROUP
, scf_strerror(scf_error()));
2154 ret
= STMF_PS_ERROR
;
2158 /* is this a SET or GET w/error? */
2160 if (scf_transaction_property_new(tran
, entry
,
2161 STMF_PERSIST_TYPE
, SCF_TYPE_ASTRING
) == -1) {
2162 syslog(LOG_ERR
, "transaction property new "
2163 "%s/%s failed - %s", STMF_DATA_GROUP
,
2165 scf_strerror(scf_error()));
2166 ret
= STMF_PS_ERROR
;
2170 if (scf_transaction_property_change(tran
, entry
,
2171 STMF_PERSIST_TYPE
, SCF_TYPE_ASTRING
) == -1) {
2172 syslog(LOG_ERR
, "transaction property change "
2173 "%s/%s failed - %s", STMF_DATA_GROUP
,
2175 scf_strerror(scf_error()));
2176 ret
= STMF_PS_ERROR
;
2182 * set the persist type
2184 if (scf_value_set_astring(value
, iPersistType
) == -1) {
2185 syslog(LOG_ERR
, "set value %s/%s failed - %s",
2186 STMF_DATA_GROUP
, STMF_PERSIST_TYPE
,
2187 scf_strerror(scf_error()));
2188 ret
= STMF_PS_ERROR
;
2193 * add the value to the transaction
2195 if (scf_entry_add_value(entry
, value
) == -1) {
2196 syslog(LOG_ERR
, "add value %s/%s failed - %s",
2197 STMF_DATA_GROUP
, STMF_PERSIST_TYPE
,
2198 scf_strerror(scf_error()));
2199 ret
= STMF_PS_ERROR
;
2202 if ((commitRet
= scf_transaction_commit(tran
)) != 1) {
2203 syslog(LOG_ERR
, "transaction commit for %s failed - %s",
2204 STMF_DATA_GROUP
, scf_strerror(scf_error()));
2205 if (commitRet
== 0) {
2206 ret
= STMF_PS_ERROR_BUSY
;
2208 ret
= STMF_PS_ERROR
;
2212 /* reset return value */
2213 ret
= STMF_PS_SUCCESS
;
2214 } else if (getSet
== GET
) {
2215 /* get the persist property */
2216 if (scf_property_get_value(prop
, value
) == -1) {
2217 syslog(LOG_ERR
, "get property value %s/%s failed - %s",
2218 STMF_DATA_GROUP
, STMF_PERSIST_TYPE
,
2219 scf_strerror(scf_error()));
2220 ret
= STMF_PS_ERROR
;
2225 * Get the value of the persist property
2227 if (scf_value_get_astring(value
, iPersistTypeGet
, MAXNAMELEN
)
2229 syslog(LOG_ERR
, "get string value %s/%s failed - %s",
2230 STMF_DATA_GROUP
, STMF_PERSIST_TYPE
,
2231 scf_strerror(scf_error()));
2232 ret
= STMF_PS_ERROR
;
2237 if (getSet
== GET
) {
2238 if (strcmp(iPersistTypeGet
, STMF_PS_PERSIST_NONE
) == 0) {
2239 *persistType
= STMF_PERSIST_NONE
;
2240 } else if (strcmp(iPersistTypeGet
, STMF_PS_PERSIST_SMF
) == 0) {
2241 *persistType
= STMF_PERSIST_SMF
;
2243 ret
= STMF_PS_ERROR
;
2250 * handle and svc should not be free'd here. They're
2257 scf_property_destroy(prop
);
2259 if (entry
!= NULL
) {
2260 scf_entry_destroy(entry
);
2263 scf_transaction_destroy(tran
);
2265 if (value
!= NULL
) {
2266 scf_value_destroy(value
);
2272 psSetStmfProp(int propType
, char *propVal
)
2274 return (iPsGetSetStmfProp(propType
, propVal
, SET
));
2278 psGetStmfProp(int propType
, char *propVal
)
2280 return (iPsGetSetStmfProp(propType
, propVal
, GET
));
2284 iPsGetSetStmfProp(int propType
, char *propVal
, int getSet
)
2286 scf_handle_t
*handle
= NULL
;
2287 scf_service_t
*svc
= NULL
;
2288 scf_property_t
*prop
= NULL
;
2289 scf_propertygroup_t
*pg
= NULL
;
2290 scf_transaction_t
*tran
= NULL
;
2291 scf_transaction_entry_t
*entry
= NULL
;
2292 scf_value_t
*value
= NULL
;
2293 char *psStmfPropVal
= NULL
;
2294 char *psStmfProp
= NULL
;
2295 char stmfPropGet
[MAXNAMELEN
] = {0};
2296 int ret
= STMF_PS_SUCCESS
;
2299 if (propVal
== NULL
|| (getSet
!= GET
&& getSet
!= SET
)) {
2300 ret
= STMF_PS_ERROR
;
2305 * Init the service handle
2308 ret
= iPsInit(&handle
, &svc
);
2309 if (ret
!= STMF_PS_SUCCESS
) {
2314 * Allocate scf resources
2317 if (((pg
= scf_pg_create(handle
)) == NULL
) ||
2318 ((prop
= scf_property_create(handle
)) == NULL
) ||
2319 ((entry
= scf_entry_create(handle
)) == NULL
) ||
2320 ((tran
= scf_transaction_create(handle
)) == NULL
) ||
2321 ((value
= scf_value_create(handle
)) == NULL
)) {
2322 syslog(LOG_ERR
, "scf alloc resource failed - %s",
2323 scf_strerror(scf_error()));
2324 ret
= STMF_PS_ERROR
;
2327 if (getSet
== GET
) {
2329 case STMF_DEFAULT_LU_STATE
:
2330 psStmfProp
= DEFAULT_LU_STATE
;
2331 psStmfPropVal
= STMF_PS_LU_ONLINE
;
2332 (void) strcpy(stmfPropGet
, psStmfPropVal
);
2334 case STMF_DEFAULT_TARGET_PORT_STATE
:
2335 psStmfProp
= DEFAULT_TARGET_PORT_STATE
;
2336 psStmfPropVal
= STMF_PS_TARGET_PORT_ONLINE
;
2337 (void) strcpy(stmfPropGet
, psStmfPropVal
);
2340 ret
= STMF_PS_ERROR
;
2344 if (getSet
== SET
) {
2346 case STMF_DEFAULT_LU_STATE
:
2347 psStmfProp
= DEFAULT_LU_STATE
;
2348 if (strcasecmp(propVal
, "online") == 0) {
2349 psStmfPropVal
= STMF_PS_LU_ONLINE
;
2350 } else if (strcasecmp(propVal
,
2352 psStmfPropVal
= STMF_PS_LU_OFFLINE
;
2354 ret
= STMF_PS_ERROR
;
2358 case STMF_DEFAULT_TARGET_PORT_STATE
:
2359 psStmfProp
= DEFAULT_TARGET_PORT_STATE
;
2360 if (strcasecmp(propVal
, "online") == 0) {
2362 STMF_PS_TARGET_PORT_ONLINE
;
2363 } else if (strcasecmp(propVal
,
2366 STMF_PS_TARGET_PORT_OFFLINE
;
2368 ret
= STMF_PS_ERROR
;
2373 ret
= STMF_PS_ERROR
;
2379 * get stmf data property group
2382 if (scf_service_get_pg(svc
, STMF_DATA_GROUP
, pg
) == -1) {
2383 if (scf_error() == SCF_ERROR_NOT_FOUND
) {
2384 ret
= STMF_PS_ERROR_NOT_FOUND
;
2386 ret
= STMF_PS_ERROR
;
2388 syslog(LOG_ERR
, "get pg %s failed - %s",
2389 STMF_DATA_GROUP
, scf_strerror(scf_error()));
2394 * get the stmf props property, if exists
2397 if (scf_pg_get_property(pg
, psStmfProp
, prop
) == -1) {
2398 if (scf_error() == SCF_ERROR_NOT_FOUND
) {
2399 ret
= STMF_PS_ERROR_NOT_FOUND
;
2401 syslog(LOG_ERR
, "start transaction for %s/%s "
2402 "failed - %s", STMF_DATA_GROUP
, psStmfProp
,
2403 scf_strerror(scf_error()));
2404 ret
= STMF_PS_ERROR
;
2409 /* if stmf prop is not found or while setting the prop */
2411 if (ret
== STMF_PS_ERROR_NOT_FOUND
|| getSet
== SET
) {
2413 * Begin the transaction
2415 if (scf_transaction_start(tran
, pg
) == -1) {
2416 syslog(LOG_ERR
, "start transaction for %s failed - %s",
2417 STMF_DATA_GROUP
, scf_strerror(scf_error()));
2418 ret
= STMF_PS_ERROR
;
2422 if (scf_transaction_property_new(tran
, entry
,
2423 psStmfProp
, SCF_TYPE_ASTRING
) == -1) {
2424 syslog(LOG_ERR
, "transaction property new "
2425 "%s/%s failed - %s", STMF_DATA_GROUP
,
2426 psStmfProp
, scf_strerror(scf_error()));
2427 ret
= STMF_PS_ERROR
;
2431 if (scf_transaction_property_change(tran
, entry
,
2432 psStmfProp
, SCF_TYPE_ASTRING
) == -1) {
2434 "transaction property change "
2435 "%s/%s failed - %s",
2436 STMF_DATA_GROUP
, psStmfProp
,
2437 scf_strerror(scf_error()));
2438 ret
= STMF_PS_ERROR
;
2444 * set stmf prop value
2447 if (scf_value_set_astring(value
, psStmfPropVal
) == -1) {
2448 syslog(LOG_ERR
, "set value %s/%s failed - %s",
2449 STMF_DATA_GROUP
, psStmfProp
,
2450 scf_strerror(scf_error()));
2451 ret
= STMF_PS_ERROR
;
2456 * add the value to the transaction
2459 if (scf_entry_add_value(entry
, value
) == -1) {
2460 syslog(LOG_ERR
, "add value %s/%s failed - %s",
2461 STMF_DATA_GROUP
, psStmfProp
,
2462 scf_strerror(scf_error()));
2463 ret
= STMF_PS_ERROR
;
2466 if ((commitRet
= scf_transaction_commit(tran
)) != 1) {
2467 syslog(LOG_ERR
, "transaction commit for %s"
2468 "failed - %s", STMF_DATA_GROUP
,
2469 scf_strerror(scf_error()));
2470 if (commitRet
== 0) {
2471 ret
= STMF_PS_ERROR_BUSY
;
2473 ret
= STMF_PS_ERROR
;
2477 ret
= STMF_PS_SUCCESS
;
2478 } else if (getSet
== GET
) {
2479 if (scf_property_get_value(prop
, value
) == -1) {
2480 syslog(LOG_ERR
, "get property value "
2481 "%s/%s failed - %s",
2482 STMF_DATA_GROUP
, psStmfProp
,
2483 scf_strerror(scf_error()));
2484 ret
= STMF_PS_ERROR
;
2490 if (scf_value_get_astring(value
, stmfPropGet
, MAXNAMELEN
)
2492 syslog(LOG_ERR
, "get string value %s/%s failed - %s",
2493 STMF_DATA_GROUP
, psStmfProp
,
2494 scf_strerror(scf_error()));
2495 ret
= STMF_PS_ERROR
;
2499 if (getSet
== GET
) {
2500 if (strcmp(stmfPropGet
, STMF_PS_LU_ONLINE
) == 0) {
2501 (void) strcpy(propVal
, "online");
2502 } else if (strcmp(stmfPropGet
, STMF_PS_LU_OFFLINE
) == 0) {
2503 (void) strcpy(propVal
, "offline");
2504 } else if (strcmp(stmfPropGet
, STMF_PS_TARGET_PORT_ONLINE
)
2506 (void) strcpy(propVal
, "online");
2507 } else if (strcmp(stmfPropGet
, STMF_PS_TARGET_PORT_OFFLINE
)
2509 (void) strcpy(propVal
, "offline");
2511 ret
= STMF_PS_ERROR
;
2520 if (handle
!= NULL
) {
2521 scf_handle_destroy(handle
);
2524 scf_service_destroy(svc
);
2530 scf_property_destroy(prop
);
2532 if (entry
!= NULL
) {
2533 scf_entry_destroy(entry
);
2536 scf_transaction_destroy(tran
);
2538 if (value
!= NULL
) {
2539 scf_value_destroy(value
);
2545 * Initialize scf stmf service access
2546 * handle - returned handle
2547 * service - returned service handle
2549 * Both handle and service must be destroyed by the caller
2552 iPsInit(scf_handle_t
**handle
, scf_service_t
**service
)
2554 scf_scope_t
*scope
= NULL
;
2558 assert(handle
!= NULL
&& service
!= NULL
);
2560 if ((*handle
= scf_handle_create(SCF_VERSION
)) == NULL
) {
2561 syslog(LOG_ERR
, "scf_handle_create failed - %s",
2562 scf_strerror(scf_error()));
2563 ret
= STMF_PS_ERROR
;
2567 if (scf_handle_bind(*handle
) == -1) {
2568 syslog(LOG_ERR
, "scf_handle_bind failed - %s",
2569 scf_strerror(scf_error()));
2570 ret
= STMF_PS_ERROR
;
2574 if ((*service
= scf_service_create(*handle
)) == NULL
) {
2575 syslog(LOG_ERR
, "scf_service_create failed - %s",
2576 scf_strerror(scf_error()));
2577 ret
= STMF_PS_ERROR
;
2581 if ((scope
= scf_scope_create(*handle
)) == NULL
) {
2582 syslog(LOG_ERR
, "scf_scope_create failed - %s",
2583 scf_strerror(scf_error()));
2584 ret
= STMF_PS_ERROR
;
2588 if (scf_handle_get_scope(*handle
, SCF_SCOPE_LOCAL
, scope
) == -1) {
2589 syslog(LOG_ERR
, "scf_handle_get_scope failed - %s",
2590 scf_strerror(scf_error()));
2591 ret
= STMF_PS_ERROR
;
2595 if (scf_scope_get_service(scope
, STMF_SERVICE
, *service
) == -1) {
2596 syslog(LOG_ERR
, "scf_scope_get_service failed - %s",
2597 scf_strerror(scf_error()));
2598 ret
= STMF_PS_ERROR_SERVICE_NOT_FOUND
;
2604 * Get and check the version number
2606 ret
= iPsGetServiceVersion(&version
, *handle
, *service
);
2607 if (ret
!= STMF_PS_SUCCESS
) {
2611 if (version
!= STMF_SMF_VERSION
) {
2612 ret
= STMF_PS_ERROR_VERSION_MISMATCH
;
2616 /* we only need destroy the scope here */
2617 scf_scope_destroy(scope
);
2619 return (STMF_PS_SUCCESS
);
2622 if (*handle
!= NULL
) {
2623 scf_handle_destroy(*handle
);
2625 if (*service
!= NULL
) {
2626 scf_service_destroy(*service
);
2629 if (scope
!= NULL
) {
2630 scf_scope_destroy(scope
);
2637 * called by iPsInit only
2638 * iPsGetServiceVersion
2641 iPsGetServiceVersion(uint64_t *version
, scf_handle_t
*handle
,
2644 scf_propertygroup_t
*pg
= NULL
;
2645 scf_property_t
*prop
= NULL
;
2646 scf_value_t
*value
= NULL
;
2647 scf_transaction_t
*tran
= NULL
;
2648 scf_transaction_entry_t
*entry
= NULL
;
2649 int ret
= STMF_PS_SUCCESS
;
2652 if (((pg
= scf_pg_create(handle
)) == NULL
) ||
2653 ((prop
= scf_property_create(handle
)) == NULL
) ||
2654 ((entry
= scf_entry_create(handle
)) == NULL
) ||
2655 ((tran
= scf_transaction_create(handle
)) == NULL
) ||
2656 ((value
= scf_value_create(handle
)) == NULL
)) {
2657 syslog(LOG_ERR
, "scf alloc resource failed - %s",
2658 scf_strerror(scf_error()));
2659 ret
= STMF_PS_ERROR
;
2663 *version
= STMF_SMF_VERSION
;
2666 * get stmf data property group
2668 if (scf_service_get_pg(svc
, STMF_DATA_GROUP
, pg
) == -1) {
2669 if (scf_error() == SCF_ERROR_NOT_FOUND
) {
2670 ret
= STMF_PS_ERROR_NOT_FOUND
;
2672 syslog(LOG_ERR
, "get pg %s failed - %s",
2673 STMF_DATA_GROUP
, scf_strerror(scf_error()));
2674 ret
= STMF_PS_ERROR
;
2679 /* create the group */
2680 if (ret
== STMF_PS_ERROR_NOT_FOUND
) {
2682 * create the property group.
2684 if (scf_service_add_pg(svc
, STMF_DATA_GROUP
,
2685 SCF_GROUP_APPLICATION
, 0, pg
) == -1) {
2686 syslog(LOG_ERR
, "add pg %s failed - %s",
2687 STMF_DATA_GROUP
, scf_strerror(scf_error()));
2688 ret
= STMF_PS_ERROR
;
2691 /* reset return value */
2692 ret
= STMF_PS_SUCCESS
;
2695 /* find version property */
2697 * Get the version property
2699 if (scf_pg_get_property(pg
, STMF_VERSION_NAME
, prop
) == -1) {
2700 if (scf_error() == SCF_ERROR_NOT_FOUND
) {
2701 ret
= STMF_PS_ERROR_NOT_FOUND
;
2703 syslog(LOG_ERR
, "get property %s/%s failed - %s",
2704 STMF_DATA_GROUP
, STMF_VERSION_NAME
,
2705 scf_strerror(scf_error()));
2706 ret
= STMF_PS_ERROR
;
2711 /* no version property found */
2712 if (ret
== STMF_PS_ERROR_NOT_FOUND
) {
2714 * If we have no version property, go ahead
2715 * and create it. We're obviously making an assumption
2716 * here that someone did not delete the existing property
2717 * and that this is the initial set and the initial call
2719 * If they did delete it, this will simply plant this
2720 * library's version on this service. That may or may not be
2721 * correct and we have no way of determining that.
2724 * Begin the transaction
2726 if (scf_transaction_start(tran
, pg
) == -1) {
2727 syslog(LOG_ERR
, "start transaction for %s failed - %s",
2728 STMF_DATA_GROUP
, scf_strerror(scf_error()));
2729 ret
= STMF_PS_ERROR
;
2733 if (scf_transaction_property_new(tran
, entry
,
2734 STMF_VERSION_NAME
, SCF_TYPE_COUNT
) == -1) {
2736 "transaction property new %s/%s failed - %s",
2737 STMF_DATA_GROUP
, STMF_VERSION_NAME
,
2738 scf_strerror(scf_error()));
2739 ret
= STMF_PS_ERROR
;
2744 * set the version number
2746 scf_value_set_count(value
, *version
);
2749 * add the value to the transaction
2751 if (scf_entry_add_value(entry
, value
) == -1) {
2752 syslog(LOG_ERR
, "add value %s/%s failed - %s",
2753 STMF_DATA_GROUP
, STMF_VERSION_NAME
,
2754 scf_strerror(scf_error()));
2755 ret
= STMF_PS_ERROR
;
2758 if ((commitRet
= scf_transaction_commit(tran
)) != 1) {
2759 syslog(LOG_ERR
, "transaction commit for %s failed - %s",
2760 STMF_DATA_GROUP
, scf_strerror(scf_error()));
2761 if (commitRet
== 0) {
2762 ret
= STMF_PS_ERROR_BUSY
;
2764 ret
= STMF_PS_ERROR
;
2768 /* reset return value */
2769 ret
= STMF_PS_SUCCESS
;
2771 /* get the version property */
2772 if (scf_pg_get_property(pg
, STMF_VERSION_NAME
, prop
) == -1) {
2773 syslog(LOG_ERR
, "get property %s/%s failed - %s",
2774 STMF_DATA_GROUP
, STMF_VERSION_NAME
,
2775 scf_strerror(scf_error()));
2776 ret
= STMF_PS_ERROR
;
2780 if (scf_property_get_value(prop
, value
) == -1) {
2781 syslog(LOG_ERR
, "get property value %s/%s failed - %s",
2782 STMF_DATA_GROUP
, STMF_VERSION_NAME
,
2783 scf_strerror(scf_error()));
2784 ret
= STMF_PS_ERROR
;
2789 * Get the actual value of the view entry count property
2791 if (scf_value_get_count(value
, version
) == -1) {
2792 syslog(LOG_ERR
, "get count value %s/%s failed - %s",
2793 STMF_DATA_GROUP
, STMF_VERSION_NAME
,
2794 scf_strerror(scf_error()));
2795 ret
= STMF_PS_ERROR
;
2803 * handle and svc should not be free'd here. They're
2810 scf_property_destroy(prop
);
2812 if (entry
!= NULL
) {
2813 scf_entry_destroy(entry
);
2816 scf_transaction_destroy(tran
);
2818 if (value
!= NULL
) {
2819 scf_value_destroy(value
);
2827 * iPsGetActualGroupName
2829 * pgName - Property group name
2830 * groupName - requested group name
2831 * actualName - actual group name to reference (len must be >= MAXNAMELEN)
2834 * STMF_PS_SUCCESS on success
2835 * STMF_PS_ERROR_* on failure
2838 iPsGetActualGroupName(char *pgName
, char *groupName
, char *actualName
)
2840 scf_handle_t
*handle
= NULL
;
2841 scf_service_t
*svc
= NULL
;
2842 scf_propertygroup_t
*pg
= NULL
;
2843 scf_property_t
*prop
= NULL
;
2844 scf_iter_t
*propIter
= NULL
;
2845 scf_value_t
*value
= NULL
;
2846 char buf
[MAXNAMELEN
];
2849 ret
= iPsInit(&handle
, &svc
);
2850 if (ret
!= STMF_PS_SUCCESS
) {
2855 * Allocate scf resources
2857 if (((pg
= scf_pg_create(handle
)) == NULL
) ||
2858 ((prop
= scf_property_create(handle
)) == NULL
) ||
2859 ((propIter
= scf_iter_create(handle
)) == NULL
) ||
2860 ((value
= scf_value_create(handle
)) == NULL
)) {
2861 syslog(LOG_ERR
, "scf alloc resource failed - %s",
2862 scf_strerror(scf_error()));
2863 ret
= STMF_PS_ERROR
;
2868 * get group list property group
2870 if (scf_service_get_pg(svc
, pgName
, pg
) == -1) {
2871 if (scf_error() == SCF_ERROR_NOT_FOUND
) {
2872 ret
= STMF_PS_ERROR_GROUP_NOT_FOUND
;
2874 syslog(LOG_ERR
, "get pg %s failed - %s",
2875 pgName
, scf_strerror(scf_error()));
2876 ret
= STMF_PS_ERROR
;
2882 * propIter is the iterator handle
2884 if (scf_iter_pg_properties(propIter
, pg
) == -1) {
2885 syslog(LOG_ERR
, "iter properties for %s failed - %s",
2886 pgName
, scf_strerror(scf_error()));
2887 ret
= STMF_PS_ERROR
;
2892 * Iterate through group properties searching for the requested
2893 * group name. When we find it, we need to get the property name
2894 * since it refers to the actual group name.
2897 /* initialize to not found */
2898 ret
= STMF_PS_ERROR_GROUP_NOT_FOUND
;
2899 while (scf_iter_next_property(propIter
, prop
) == 1) {
2900 if (scf_property_get_name(prop
, actualName
, MAXNAMELEN
) == -1) {
2901 syslog(LOG_ERR
, "get name from %s iter failed - %s",
2902 pgName
, scf_strerror(scf_error()));
2903 ret
= STMF_PS_ERROR
;
2907 * Skip over non-member list properties
2909 if (strstr(actualName
, STMF_MEMBER_LIST_SUFFIX
)) {
2912 if (scf_property_get_value(prop
, value
) == -1) {
2913 syslog(LOG_ERR
, "get property value %s/%s failed - %s",
2914 pgName
, actualName
, scf_strerror(scf_error()));
2915 ret
= STMF_PS_ERROR
;
2918 if (scf_value_get_ustring(value
, buf
, sizeof (buf
)) == -1) {
2919 syslog(LOG_ERR
, "get ustring %s/%s failed - %s",
2920 pgName
, actualName
, scf_strerror(scf_error()));
2921 ret
= STMF_PS_ERROR
;
2926 * When we find a match, set success and break
2928 if ((strlen(buf
) == strlen(groupName
)) &&
2929 bcmp(buf
, groupName
, strlen(buf
)) == 0) {
2930 ret
= STMF_PS_SUCCESS
;
2936 * if we didn't find it, ret is set to STMF_PS_ERROR_GROUP_NOT_FOUND
2943 if (handle
!= NULL
) {
2944 scf_handle_destroy(handle
);
2947 scf_service_destroy(svc
);
2952 if (propIter
!= NULL
) {
2953 scf_iter_destroy(propIter
);
2956 scf_property_destroy(prop
);
2958 if (value
!= NULL
) {
2959 scf_value_destroy(value
);
2966 * psAddHostGroupMember
2968 * Add a host group member to a host group,
2970 * Input: groupName - name of group to which the member is added
2971 * memberName - name of group member to add
2974 psAddHostGroupMember(char *groupName
, char *memberName
)
2977 char groupPropListName
[MAXNAMELEN
];
2978 char groupPropName
[MAXNAMELEN
];
2980 ret
= iPsGetActualGroupName(STMF_HOST_GROUPS
, groupName
,
2982 if (ret
!= STMF_PS_SUCCESS
) {
2986 if (snprintf(groupPropListName
, sizeof (groupPropListName
),
2987 "%s-%s", groupPropName
, STMF_MEMBER_LIST_SUFFIX
) >
2988 sizeof (groupPropListName
)) {
2989 syslog(LOG_ERR
, "buffer overflow on property name %s",
2991 return (STMF_PS_ERROR
);
2994 return (iPsAddRemoveGroupMember(STMF_HOST_GROUPS
, groupPropListName
,
2999 * psAddTargetGroupMember
3001 * Add a target port group member to a target group
3003 * Input: groupName - name of group to which the member is added
3004 * memberName - name of group member to add. Must be nul terminated.
3007 psAddTargetGroupMember(char *groupName
, char *memberName
)
3010 char groupPropListName
[MAXNAMELEN
];
3011 char groupPropName
[MAXNAMELEN
];
3013 ret
= iPsGetActualGroupName(STMF_TARGET_GROUPS
, groupName
,
3015 if (ret
!= STMF_PS_SUCCESS
) {
3019 if (snprintf(groupPropListName
, sizeof (groupPropListName
),
3020 "%s-%s", groupPropName
, STMF_MEMBER_LIST_SUFFIX
) >
3021 sizeof (groupPropListName
)) {
3022 syslog(LOG_ERR
, "buffer overflow on property name %s",
3024 return (STMF_PS_ERROR
);
3027 return (iPsAddRemoveGroupMember(STMF_TARGET_GROUPS
, groupPropListName
,
3035 * luGuid - logical unit identifier
3036 * viewEntry - pointer to viewEntry allocated by the caller that contains
3037 * the values to set for this view entry
3040 * STMF_PS_SUCCESS on success
3041 * STMF_PS_ERROR_* on failure
3044 psAddViewEntry(stmfGuid
*lu
, stmfViewEntry
*viewEntry
)
3046 scf_handle_t
*handle
= NULL
;
3047 scf_service_t
*svc
= NULL
;
3048 scf_propertygroup_t
*pg
= NULL
;
3049 char guidAsciiBuf
[33]; /* size of ascii hex 16 byte guid with NULL */
3050 char viewEntryPgName
[VIEW_ENTRY_PG_SIZE
];
3051 char scfLuPgName
[LOGICAL_UNIT_PG_SIZE
];
3052 int ret
= STMF_PS_SUCCESS
;
3053 sigset_t sigmaskRestore
;
3055 /* grab the signal hold lock */
3056 (void) pthread_mutex_lock(&sigSetLock
);
3059 * hold signals until we're done
3061 if (holdSignal(&sigmaskRestore
) != 0) {
3062 (void) pthread_mutex_unlock(&sigSetLock
);
3063 return (STMF_PS_ERROR
);
3066 ret
= iPsInit(&handle
, &svc
);
3067 if (ret
!= STMF_PS_SUCCESS
) {
3071 pg
= scf_pg_create(handle
);
3073 syslog(LOG_ERR
, "scf pg alloc failed - %s",
3074 scf_strerror(scf_error()));
3075 ret
= STMF_PS_ERROR
;
3079 /* Convert to ASCII uppercase hexadecimal string */
3080 (void) snprintf(guidAsciiBuf
, sizeof (guidAsciiBuf
),
3081 "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
3082 lu
->guid
[0], lu
->guid
[1], lu
->guid
[2], lu
->guid
[3], lu
->guid
[4],
3083 lu
->guid
[5], lu
->guid
[6], lu
->guid
[7], lu
->guid
[8], lu
->guid
[9],
3084 lu
->guid
[10], lu
->guid
[11], lu
->guid
[12], lu
->guid
[13],
3085 lu
->guid
[14], lu
->guid
[15]);
3087 (void) snprintf(scfLuPgName
, sizeof (scfLuPgName
), "%s-%s",
3088 STMF_LU_PREFIX
, guidAsciiBuf
);
3090 bzero(viewEntryPgName
, sizeof (viewEntryPgName
));
3092 * Format of view entry property group name:
3093 * VE-<view_entry_name>-<lu_name>
3095 (void) snprintf(viewEntryPgName
, sizeof (viewEntryPgName
),
3096 "%s-%d-%s", STMF_VE_PREFIX
, viewEntry
->veIndex
, guidAsciiBuf
);
3098 ret
= iPsAddViewEntry(scfLuPgName
, viewEntryPgName
, viewEntry
);
3102 * Okay, we're done. Release the signals
3104 if (releaseSignal(&sigmaskRestore
) != 0) {
3106 * Don't set this as an STMF_PS_ERROR_*. We succeeded
3107 * the requested operation. But we do need to log it.
3109 syslog(LOG_ERR
, "Unable to release one or more signals - %s",
3116 if (handle
!= NULL
) {
3117 scf_handle_destroy(handle
);
3120 scf_service_destroy(svc
);
3126 /* release the signal hold lock */
3127 (void) pthread_mutex_unlock(&sigSetLock
);
3135 * Purpose: Checks whether service exists
3142 scf_handle_t
*handle
= NULL
;
3143 scf_service_t
*svc
= NULL
;
3145 ret
= iPsInit(&handle
, &svc
);
3150 if (handle
!= NULL
) {
3151 scf_handle_destroy(handle
);
3154 scf_service_destroy(svc
);
3163 * groupName - name of group to create
3166 * STMF_PS_SUCCESS on success
3167 * STMF_PS_ERROR_* on failure
3170 psCreateHostGroup(char *groupName
)
3172 return (iPsCreateDeleteGroup(STMF_HOST_GROUPS
, groupName
, ADD
));
3176 * psCreateTargetGroup
3178 * groupName - name of group to create
3181 * STMF_PS_SUCCESS on success
3182 * STMF_PS_ERROR_* on failure
3185 psCreateTargetGroup(char *groupName
)
3187 return (iPsCreateDeleteGroup(STMF_TARGET_GROUPS
, groupName
, ADD
));
3193 * groupName - name of group to delete
3196 * STMF_PS_SUCCESS on success
3197 * STMF_PS_ERROR_* on failure
3200 psDeleteHostGroup(char *groupName
)
3202 return (iPsCreateDeleteGroup(STMF_HOST_GROUPS
, groupName
, REMOVE
));
3206 * psDeleteTargetGroup
3208 * groupName - name of group to delete
3211 * STMF_PS_SUCCESS on success
3212 * STMF_PS_ERROR_* on failure
3215 psDeleteTargetGroup(char *groupName
)
3217 return (iPsCreateDeleteGroup(STMF_TARGET_GROUPS
, groupName
,
3222 * psGetHostGroupList
3224 * groupList - pointer to pointer to stmfGroupList. Contains the list
3225 * of host groups on successful return.
3228 * STMF_PS_SUCCESS on success
3229 * STMF_PS_ERROR_* on failure
3232 psGetHostGroupList(stmfGroupList
**groupList
)
3234 return (iPsGetGroupList(STMF_HOST_GROUPS
, groupList
));
3238 * psGetLogicalUnitList
3243 psGetLogicalUnitList(stmfGuidList
**guidList
)
3245 scf_handle_t
*handle
= NULL
;
3246 scf_service_t
*svc
= NULL
;
3247 scf_propertygroup_t
*pg
= NULL
;
3248 scf_iter_t
*pgIter
= NULL
;
3249 char buf
[MAXNAMELEN
];
3252 int ret
= STMF_PS_SUCCESS
;
3253 unsigned int guid
[sizeof (stmfGuid
)];
3256 assert(guidList
!= NULL
);
3258 ret
= iPsInit(&handle
, &svc
);
3259 if (ret
!= STMF_PS_SUCCESS
) {
3264 * Allocate scf resources
3266 if (((pg
= scf_pg_create(handle
)) == NULL
) ||
3267 ((pgIter
= scf_iter_create(handle
)) == NULL
)) {
3268 syslog(LOG_ERR
, "scf alloc resource failed - %s",
3269 scf_strerror(scf_error()));
3270 ret
= STMF_PS_ERROR
;
3275 * pgIter is the iterator handle
3277 if (scf_iter_service_pgs(pgIter
, svc
) == -1) {
3278 syslog(LOG_ERR
, "iter property groups failed - %s",
3279 scf_strerror(scf_error()));
3280 ret
= STMF_PS_ERROR
;
3284 while (scf_iter_next_pg(pgIter
, pg
) == 1) {
3285 if (scf_pg_get_name(pg
, buf
, sizeof (buf
)) == -1) {
3286 syslog(LOG_ERR
, "get pg name failed - %s",
3287 scf_strerror(scf_error()));
3288 ret
= STMF_PS_ERROR
;
3292 * Only count LU property groups
3294 if (strncmp(buf
, STMF_LU_PREFIX
, strlen(STMF_LU_PREFIX
)) == 0) {
3300 * pgIter is the iterator handle
3302 if (scf_iter_service_pgs(pgIter
, svc
) == -1) {
3303 syslog(LOG_ERR
, "iter property groups failed - %s",
3304 scf_strerror(scf_error()));
3305 ret
= STMF_PS_ERROR
;
3309 *guidList
= (stmfGuidList
*)calloc(1, sizeof (stmfGuidList
) +
3310 guidCnt
* sizeof (stmfGuid
));
3311 if (*guidList
== NULL
) {
3312 ret
= STMF_PS_ERROR_NOMEM
;
3317 * it's possible for entries to be added/removed while we're retrieving
3318 * the property groups. Just make sure we don't write beyond our
3319 * allocated buffer by checking to ensure i < guidCnt.
3321 while ((scf_iter_next_pg(pgIter
, pg
) == 1) && (i
< guidCnt
)) {
3322 if (scf_pg_get_name(pg
, buf
, sizeof (buf
)) == -1) {
3323 syslog(LOG_ERR
, "get pg name failed - %s",
3324 scf_strerror(scf_error()));
3325 ret
= STMF_PS_ERROR
;
3329 * Only use LU property groups
3331 if (strncmp(buf
, STMF_LU_PREFIX
, strlen(STMF_LU_PREFIX
)) != 0) {
3335 j
= strlen(STMF_LU_PREFIX
) + strlen("-");
3337 (void) sscanf(buf
+ j
,
3338 "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
3339 &guid
[0], &guid
[1], &guid
[2], &guid
[3], &guid
[4], &guid
[5],
3340 &guid
[6], &guid
[7], &guid
[8], &guid
[9], &guid
[10],
3341 &guid
[11], &guid
[12], &guid
[13], &guid
[14], &guid
[15]);
3343 for (j
= 0; j
< sizeof (stmfGuid
); j
++) {
3344 outGuid
.guid
[j
] = guid
[j
];
3347 bcopy(&outGuid
, (*guidList
)->guid
[i
++].guid
, sizeof (stmfGuid
));
3351 if (ret
!= STMF_PS_SUCCESS
) {
3360 if (handle
!= NULL
) {
3361 scf_handle_destroy(handle
);
3364 scf_service_destroy(svc
);
3369 if (pgIter
!= NULL
) {
3370 scf_iter_destroy(pgIter
);
3377 * psGetTargetGroupList
3379 * groupList - pointer to pointer to stmfGroupList. Contains the list
3380 * of target groups on successful return.
3383 * STMF_PS_SUCCESS on success
3384 * STMF_PS_ERROR_* on failure
3387 psGetTargetGroupList(stmfGroupList
**groupList
)
3389 return (iPsGetGroupList(STMF_TARGET_GROUPS
, groupList
));
3393 * psGetHostGroupMemberList
3395 * groupName - group name for which to retrieve a member list
3396 * groupMemberList - pointer to pointer to stmfGroupProperties list
3399 * STMF_PS_SUCCESS on success
3400 * STMF_PS_ERROR_* on failure
3403 psGetHostGroupMemberList(char *groupName
, stmfGroupProperties
**groupMemberList
)
3406 char groupPropListName
[MAXNAMELEN
];
3407 char groupPropName
[MAXNAMELEN
];
3409 ret
= iPsGetActualGroupName(STMF_HOST_GROUPS
, groupName
,
3411 if (ret
!= STMF_PS_SUCCESS
) {
3415 if (snprintf(groupPropListName
, sizeof (groupPropListName
),
3416 "%s-%s", groupPropName
, STMF_MEMBER_LIST_SUFFIX
) >
3417 sizeof (groupPropListName
)) {
3418 syslog(LOG_ERR
, "buffer overflow on property name %s",
3420 return (STMF_PS_ERROR
);
3423 return (iPsGetGroupMemberList(STMF_HOST_GROUPS
, groupPropListName
,
3428 * psGetTargetGroupMemberList
3430 * groupName - group name for which to retrieve a member list
3431 * groupMemberList - pointer to pointer to stmfGroupProperties list
3434 * STMF_PS_SUCCESS on success
3435 * STMF_PS_ERROR_* on failure
3438 psGetTargetGroupMemberList(char *groupName
,
3439 stmfGroupProperties
**groupMemberList
)
3442 char groupPropListName
[MAXNAMELEN
];
3443 char groupPropName
[MAXNAMELEN
];
3445 ret
= iPsGetActualGroupName(STMF_TARGET_GROUPS
, groupName
,
3447 if (ret
!= STMF_PS_SUCCESS
) {
3451 if (snprintf(groupPropListName
, sizeof (groupPropListName
),
3452 "%s-%s", groupPropName
, STMF_MEMBER_LIST_SUFFIX
) >
3453 sizeof (groupPropListName
)) {
3454 syslog(LOG_ERR
, "buffer overflow on property name %s",
3456 return (STMF_PS_ERROR
);
3459 return (iPsGetGroupMemberList(STMF_TARGET_GROUPS
,
3460 groupPropListName
, groupMemberList
));
3468 viewEntryCompare(const void *p1
, const void *p2
)
3471 stmfViewEntry
*v1
= (stmfViewEntry
*)p1
, *v2
= (stmfViewEntry
*)p2
;
3472 if (v1
->veIndex
> v2
->veIndex
)
3474 if (v1
->veIndex
< v2
->veIndex
)
3480 * psGetViewEntryList
3482 * luGuid - identifier of logical unit for which to retrieve a view entry list
3483 * viewEntryList - pointer to pointer to stmfViewEntryList. It will be allocated
3484 * on successful return.
3487 * STMF_PS_SUCCESS on success
3488 * STMF_PS_ERROR_* on failure
3491 psGetViewEntryList(stmfGuid
*lu
, stmfViewEntryList
**viewEntryList
)
3493 scf_handle_t
*handle
= NULL
;
3494 scf_service_t
*svc
= NULL
;
3495 scf_propertygroup_t
*pg
= NULL
;
3496 scf_property_t
*prop
= NULL
;
3497 scf_value_t
*value
= NULL
;
3498 scf_iter_t
*propIter
= NULL
;
3499 char guidAsciiBuf
[33]; /* size of ascii hex 16 byte guid with NULL */
3500 char viewEntryPgName
[VIEW_ENTRY_PG_SIZE
];
3501 char luPgName
[LOGICAL_UNIT_PG_SIZE
];
3502 int ret
= STMF_PS_SUCCESS
;
3507 ret
= iPsInit(&handle
, &svc
);
3508 if (ret
!= STMF_PS_SUCCESS
) {
3513 * Allocate scf resources
3515 if (((pg
= scf_pg_create(handle
)) == NULL
) ||
3516 ((prop
= scf_property_create(handle
)) == NULL
) ||
3517 ((propIter
= scf_iter_create(handle
)) == NULL
) ||
3518 ((value
= scf_value_create(handle
)) == NULL
)) {
3519 syslog(LOG_ERR
, "scf alloc resource failed - %s",
3520 scf_strerror(scf_error()));
3521 ret
= STMF_PS_ERROR
;
3525 /* Convert to ASCII uppercase hexadecimal string */
3526 (void) snprintf(guidAsciiBuf
, sizeof (guidAsciiBuf
),
3527 "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
3528 lu
->guid
[0], lu
->guid
[1], lu
->guid
[2], lu
->guid
[3], lu
->guid
[4],
3529 lu
->guid
[5], lu
->guid
[6], lu
->guid
[7], lu
->guid
[8], lu
->guid
[9],
3530 lu
->guid
[10], lu
->guid
[11], lu
->guid
[12], lu
->guid
[13],
3531 lu
->guid
[14], lu
->guid
[15]);
3533 /* form the LU property group name (LU-<guid>) */
3534 (void) snprintf(luPgName
, sizeof (luPgName
), "%s-%s",
3535 STMF_LU_PREFIX
, guidAsciiBuf
);
3537 /* get the property group associated with this LU */
3538 if (scf_service_get_pg(svc
, luPgName
, pg
) == -1) {
3539 if (scf_error() == SCF_ERROR_NOT_FOUND
) {
3540 ret
= STMF_PS_ERROR_NOT_FOUND
;
3542 syslog(LOG_ERR
, "get pg %s failed - %s",
3543 luPgName
, scf_strerror(scf_error()));
3544 ret
= STMF_PS_ERROR
;
3549 /* get the view entry count property */
3550 if (scf_pg_get_property(pg
, STMF_VE_CNT
, prop
) == -1) {
3551 syslog(LOG_ERR
, "get property %s/%s failed - %s",
3552 luPgName
, STMF_VE_CNT
, scf_strerror(scf_error()));
3553 ret
= STMF_PS_ERROR
;
3557 if (scf_property_get_value(prop
, value
) == -1) {
3558 syslog(LOG_ERR
, "get property value %s/%s failed - %s",
3559 luPgName
, STMF_VE_CNT
, scf_strerror(scf_error()));
3560 ret
= STMF_PS_ERROR
;
3565 * Get the actual value of the view entry count property
3567 if (scf_value_get_count(value
, &veCnt
) == -1) {
3568 syslog(LOG_ERR
, "get integer value %s/%s failed - %s",
3569 luPgName
, STMF_VE_CNT
, scf_strerror(scf_error()));
3570 ret
= STMF_PS_ERROR
;
3575 * propIter is the iterator handle
3577 if (scf_iter_pg_properties(propIter
, pg
) == -1) {
3578 syslog(LOG_ERR
, "iter properties for %s failed - %s",
3579 luPgName
, scf_strerror(scf_error()));
3580 ret
= STMF_PS_ERROR
;
3585 * alloc the list based on the view entry count
3587 *viewEntryList
= (stmfViewEntryList
*)calloc(1,
3588 sizeof (stmfViewEntryList
) + veCnt
* sizeof (stmfViewEntry
));
3589 if (*viewEntryList
== NULL
) {
3590 ret
= STMF_PS_ERROR_NOMEM
;
3596 * iterate through the view entry properties to find the
3599 while (scf_iter_next_property(propIter
, prop
) == 1) {
3600 /* find match for view entry property */
3601 if (scf_property_get_name(prop
, viewEntryPgName
,
3602 sizeof (viewEntryPgName
)) != -1) {
3603 if (strncmp(viewEntryPgName
, STMF_VE_PREFIX
,
3604 strlen(STMF_VE_PREFIX
)) != 0) {
3608 * We've exceeded our alloc limit
3612 ret
= STMF_PS_ERROR
;
3616 if ((ret
= iPsGetViewEntry(viewEntryPgName
,
3617 &((*viewEntryList
)->ve
[i
]))) != STMF_PS_SUCCESS
) {
3623 /* set the list count */
3624 (*viewEntryList
)->cnt
++;
3626 syslog(LOG_ERR
, "scf iter %s properties failed - %s",
3627 luPgName
, scf_strerror(scf_error()));
3628 ret
= STMF_PS_ERROR
;
3634 if (ret
!= STMF_PS_SUCCESS
) {
3635 free(*viewEntryList
);
3640 * We're sorting the final list here based on the veIndex
3641 * If we don't, the caller is going to have to do it to reap
3642 * some intelligent output.
3644 qsort((void *)&((*viewEntryList
)->ve
[0]), (*viewEntryList
)->cnt
,
3645 sizeof (stmfViewEntry
), viewEntryCompare
);
3651 if (handle
!= NULL
) {
3652 scf_handle_destroy(handle
);
3655 scf_service_destroy(svc
);
3661 scf_property_destroy(prop
);
3663 if (value
!= NULL
) {
3664 scf_value_destroy(value
);
3666 if (propIter
!= NULL
) {
3667 scf_iter_destroy(propIter
);
3676 * viewEntryPgName - view entry property group name to retrieve
3677 * viewEntry - pointer to stmfViewEntry structure allocated by the caller
3680 * STMF_PS_SUCCESS on success
3681 * STMF_PS_ERROR_* on failure
3684 iPsGetViewEntry(char *viewEntryPgName
, stmfViewEntry
*viewEntry
)
3686 scf_handle_t
*handle
= NULL
;
3687 scf_service_t
*svc
= NULL
;
3688 scf_propertygroup_t
*pg
= NULL
;
3689 scf_property_t
*prop
= NULL
;
3690 scf_value_t
*value
= NULL
;
3693 char groupName
[sizeof (stmfGroupName
)];
3694 int ret
= STMF_PS_SUCCESS
;
3697 ret
= iPsInit(&handle
, &svc
);
3698 if (ret
!= STMF_PS_SUCCESS
) {
3703 * Allocate scf resources
3705 if (((pg
= scf_pg_create(handle
)) == NULL
) ||
3706 ((prop
= scf_property_create(handle
)) == NULL
) ||
3707 ((value
= scf_value_create(handle
)) == NULL
)) {
3708 syslog(LOG_ERR
, "scf alloc resource failed - %s",
3709 scf_strerror(scf_error()));
3710 ret
= STMF_PS_ERROR
;
3714 bzero(viewEntry
, sizeof (stmfViewEntry
));
3717 * get the service property group view entry handle
3719 if (scf_service_get_pg(svc
, viewEntryPgName
, pg
) == -1) {
3720 if (scf_error() == SCF_ERROR_NOT_FOUND
) {
3721 ret
= STMF_PS_ERROR_NOT_FOUND
;
3723 syslog(LOG_ERR
, "get pg %s failed - %s",
3724 viewEntryPgName
, scf_strerror(scf_error()));
3725 ret
= STMF_PS_ERROR
;
3733 * format is: VE-<veIndex>-GUID
3735 indexPtr
= strchr(viewEntryPgName
, '-');
3737 ret
= STMF_PS_ERROR
;
3742 viewEntry
->veIndex
= atoi(strtok(++indexPtr
, "-"));
3744 viewEntry
->veIndexValid
= B_TRUE
;
3746 /* get allHosts property */
3747 if (scf_pg_get_property(pg
, STMF_VE_ALLHOSTS
,
3749 syslog(LOG_ERR
, "get property %s/%s failed - %s",
3750 viewEntryPgName
, STMF_VE_ALLHOSTS
,
3751 scf_strerror(scf_error()));
3752 ret
= STMF_PS_ERROR
;
3756 if (scf_property_get_value(prop
, value
) == -1) {
3757 syslog(LOG_ERR
, "get property %s/%s failed - %s",
3758 viewEntryPgName
, STMF_VE_ALLHOSTS
,
3759 scf_strerror(scf_error()));
3760 ret
= STMF_PS_ERROR
;
3765 if (scf_value_get_boolean(value
, (uint8_t *)&scfBool
) == -1) {
3766 syslog(LOG_ERR
, "get property %s/%s failed - %s",
3767 viewEntryPgName
, STMF_VE_ALLHOSTS
,
3768 scf_strerror(scf_error()));
3769 ret
= STMF_PS_ERROR
;
3772 viewEntry
->allHosts
= scfBool
;
3774 /* get hostGroup property */
3775 if (scf_pg_get_property(pg
, STMF_VE_HOSTGROUP
,
3777 syslog(LOG_ERR
, "get property %s/%s failed - %s",
3778 viewEntryPgName
, STMF_VE_HOSTGROUP
,
3779 scf_strerror(scf_error()));
3780 ret
= STMF_PS_ERROR
;
3784 if (scf_property_get_value(prop
, value
) == -1) {
3785 syslog(LOG_ERR
, "get property %s/%s failed - %s",
3786 viewEntryPgName
, STMF_VE_HOSTGROUP
,
3787 scf_strerror(scf_error()));
3788 ret
= STMF_PS_ERROR
;
3792 if (scf_value_get_ustring(value
, groupName
,
3793 sizeof (groupName
)) == -1) {
3794 syslog(LOG_ERR
, "get value %s/%s failed - %s",
3795 viewEntryPgName
, STMF_VE_HOSTGROUP
,
3796 scf_strerror(scf_error()));
3797 ret
= STMF_PS_ERROR
;
3801 bcopy(groupName
, viewEntry
->hostGroup
, strlen(groupName
));
3803 /* get allTargets property */
3804 if (scf_pg_get_property(pg
, STMF_VE_ALLTARGETS
,
3806 syslog(LOG_ERR
, "get property %s/%s failed - %s",
3807 viewEntryPgName
, STMF_VE_ALLTARGETS
,
3808 scf_strerror(scf_error()));
3809 ret
= STMF_PS_ERROR
;
3813 if (scf_property_get_value(prop
, value
) == -1) {
3814 syslog(LOG_ERR
, "get property value %s/%s failed - %s",
3815 viewEntryPgName
, STMF_VE_ALLTARGETS
,
3816 scf_strerror(scf_error()));
3817 ret
= STMF_PS_ERROR
;
3821 /* set allTargets */
3822 if (scf_value_get_boolean(value
, (uint8_t *)&scfBool
) == -1) {
3823 syslog(LOG_ERR
, "get value %s/%s failed - %s",
3824 viewEntryPgName
, STMF_VE_ALLTARGETS
,
3825 scf_strerror(scf_error()));
3826 ret
= STMF_PS_ERROR
;
3829 viewEntry
->allTargets
= scfBool
;
3831 /* get targetGroup property */
3832 if (scf_pg_get_property(pg
, STMF_VE_TARGETGROUP
, prop
) == -1) {
3833 syslog(LOG_ERR
, "get property %s/%s failed - %s",
3834 viewEntryPgName
, STMF_VE_TARGETGROUP
,
3835 scf_strerror(scf_error()));
3836 ret
= STMF_PS_ERROR
;
3840 if (scf_property_get_value(prop
, value
) == -1) {
3841 syslog(LOG_ERR
, "get property value %s/%s failed - %s",
3842 viewEntryPgName
, STMF_VE_TARGETGROUP
,
3843 scf_strerror(scf_error()));
3844 ret
= STMF_PS_ERROR
;
3848 if (scf_value_get_ustring(value
, groupName
,
3849 sizeof (groupName
)) == -1) {
3850 syslog(LOG_ERR
, "get value %s/%s failed - %s",
3851 viewEntryPgName
, STMF_VE_TARGETGROUP
,
3852 scf_strerror(scf_error()));
3853 ret
= STMF_PS_ERROR
;
3856 /* set targetGroup */
3857 bcopy(groupName
, viewEntry
->targetGroup
, strlen(groupName
));
3859 /* get luNbr property */
3860 if (scf_pg_get_property(pg
, STMF_VE_LUNBR
,
3862 syslog(LOG_ERR
, "get property %s/%s failed - %s",
3863 viewEntryPgName
, STMF_VE_LUNBR
,
3864 scf_strerror(scf_error()));
3865 ret
= STMF_PS_ERROR
;
3869 if (scf_property_get_value(prop
, value
) == -1) {
3870 syslog(LOG_ERR
, "get property value %s/%s failed - %s",
3871 viewEntryPgName
, STMF_VE_LUNBR
,
3872 scf_strerror(scf_error()));
3873 ret
= STMF_PS_ERROR
;
3878 if (scf_value_get_opaque(value
, (char *)viewEntry
->luNbr
,
3879 sizeof (viewEntry
->luNbr
)) == -1) {
3880 syslog(LOG_ERR
, "get opaque value %s/%s failed - %s",
3881 viewEntryPgName
, STMF_VE_LUNBR
,
3882 scf_strerror(scf_error()));
3883 ret
= STMF_PS_ERROR
;
3886 /* set luNbrValid to true since we just got it */
3887 viewEntry
->luNbrValid
= B_TRUE
;
3893 if (handle
!= NULL
) {
3894 scf_handle_destroy(handle
);
3897 scf_service_destroy(svc
);
3902 if (value
!= NULL
) {
3903 scf_value_destroy(value
);
3906 scf_property_destroy(prop
);
3914 * psRemoveHostGroupMember
3916 * Remove a host group member from a host group,
3918 * groupName - name of group from which the member is removed
3919 * memberName - name of group member to remove
3922 * STMF_PS_SUCCESS on success
3923 * STMF_PS_ERROR_* on failure
3926 psRemoveHostGroupMember(char *groupName
, char *memberName
)
3929 char groupPropListName
[MAXNAMELEN
];
3930 char groupPropName
[MAXNAMELEN
];
3932 ret
= iPsGetActualGroupName(STMF_HOST_GROUPS
, groupName
,
3934 if (ret
!= STMF_PS_SUCCESS
) {
3938 if (snprintf(groupPropListName
, sizeof (groupPropListName
),
3939 "%s-%s", groupPropName
, STMF_MEMBER_LIST_SUFFIX
) >
3940 sizeof (groupPropListName
)) {
3941 syslog(LOG_ERR
, "buffer overflow on property name %s",
3943 return (STMF_PS_ERROR
);
3946 return (iPsAddRemoveGroupMember(STMF_HOST_GROUPS
, groupPropListName
,
3947 memberName
, REMOVE
));
3951 * psRemoveTargetGroupMember
3953 * Remove a target port group member from an target port group,
3955 * groupName - name of group from which the member is removed
3956 * memberName - name of group member to remove
3959 * STMF_PS_SUCCESS on success
3960 * STMF_PS_ERROR_* on failure
3963 psRemoveTargetGroupMember(char *groupName
, char *memberName
)
3966 char groupPropListName
[MAXNAMELEN
];
3967 char groupPropName
[MAXNAMELEN
];
3969 ret
= iPsGetActualGroupName(STMF_TARGET_GROUPS
, groupName
,
3971 if (ret
!= STMF_PS_SUCCESS
) {
3975 if (snprintf(groupPropListName
, sizeof (groupPropListName
),
3976 "%s-%s", groupPropName
, STMF_MEMBER_LIST_SUFFIX
) >
3977 sizeof (groupPropListName
)) {
3978 syslog(LOG_ERR
, "buffer overflow on property name %s",
3980 return (STMF_PS_ERROR
);
3983 return (iPsAddRemoveGroupMember(STMF_TARGET_GROUPS
, groupPropListName
,
3984 memberName
, REMOVE
));
3990 * Retrieves an nvlist on a per provider basis
3992 * providerName - property group name to use
3993 * nvl - nvlist to retrieve
3997 psGetProviderData(char *providerName
, nvlist_t
**nvl
, int providerType
,
4000 scf_handle_t
*handle
= NULL
;
4001 scf_service_t
*svc
= NULL
;
4002 scf_propertygroup_t
*pg
= NULL
;
4003 scf_property_t
*prop
= NULL
;
4004 scf_value_t
*value
= NULL
;
4005 uint64_t blockCnt
= 0;
4006 ssize_t blockOffset
= 0;
4007 ssize_t actualBlockSize
= 0;
4008 char pgName
[MAXPATHLEN
];
4009 char dataPropertyName
[STMF_PROVIDER_DATA_PROP_NAME_SIZE
];
4010 char *nvlistEncoded
= NULL
;
4011 ssize_t nvlistEncodedSize
= 0;
4012 boolean_t foundSetCnt
= B_TRUE
;
4014 int ret
= STMF_PS_SUCCESS
;
4016 if (providerName
== NULL
|| (providerType
!= STMF_LU_PROVIDER_TYPE
&&
4017 providerType
!= STMF_PORT_PROVIDER_TYPE
)) {
4018 ret
= STMF_PS_ERROR_INVALID_ARG
;
4022 ret
= iPsInit(&handle
, &svc
);
4023 if (ret
!= STMF_PS_SUCCESS
) {
4028 * create the property group name
4030 (void) snprintf(pgName
, sizeof (pgName
), "%s%s",
4031 STMF_PROVIDER_DATA_PREFIX
, providerName
);
4034 * Allocate scf resources
4036 if (((pg
= scf_pg_create(handle
)) == NULL
) ||
4037 ((value
= scf_value_create(handle
)) == NULL
) ||
4038 ((prop
= scf_property_create(handle
)) == NULL
)) {
4039 syslog(LOG_ERR
, "scf alloc resource failed - %s",
4040 scf_strerror(scf_error()));
4041 ret
= STMF_PS_ERROR
;
4046 * Retrieve the existing property group.
4048 if (scf_service_get_pg(svc
, pgName
, pg
) == -1) {
4049 if (scf_error() != SCF_ERROR_NOT_FOUND
) {
4050 syslog(LOG_ERR
, "get pg %s failed - %s", pgName
,
4051 scf_strerror(scf_error()));
4052 ret
= STMF_PS_ERROR
;
4055 ret
= STMF_PS_ERROR_NOT_FOUND
;
4061 * Get the STMF_PROVIDER_DATA_PROP_COUNT property
4063 if (scf_pg_get_property(pg
, STMF_PROVIDER_DATA_PROP_COUNT
,
4065 syslog(LOG_ERR
, "get property %s/%s failed - %s",
4066 pgName
, STMF_PROVIDER_DATA_PROP_COUNT
,
4067 scf_strerror(scf_error()));
4068 ret
= STMF_PS_ERROR
;
4073 * Get the STMF_PROVIDER_DATA_PROP_COUNT value
4075 if (scf_property_get_value(prop
, value
) == -1) {
4076 syslog(LOG_ERR
, "get property value %s/%s failed - %s",
4077 pgName
, STMF_PROVIDER_DATA_PROP_COUNT
,
4078 scf_strerror(scf_error()));
4079 ret
= STMF_PS_ERROR
;
4084 * Now get the actual value from the value handle
4086 if (scf_value_get_count(value
, &blockCnt
) == -1) {
4087 syslog(LOG_ERR
, "get integer value %s/%s failed - %s",
4088 pgName
, STMF_PROVIDER_DATA_PROP_COUNT
,
4089 scf_strerror(scf_error()));
4090 ret
= STMF_PS_ERROR
;
4094 /* Has the caller requested the token to be set? */
4097 * Get the STMF_PROVIDER_DATA_PROP_SET_COUNT property
4098 * If it doesn't exist, we assume it to be zero.
4101 if (scf_pg_get_property(pg
, STMF_PROVIDER_DATA_PROP_SET_COUNT
,
4103 if (scf_error() == SCF_ERROR_NOT_FOUND
) {
4104 foundSetCnt
= B_FALSE
;
4106 syslog(LOG_ERR
, "get property %s/%s "
4107 "failed - %s", pgName
,
4108 STMF_PROVIDER_DATA_PROP_SET_COUNT
,
4109 scf_strerror(scf_error()));
4110 ret
= STMF_PS_ERROR
;
4117 * Get the STMF_PROVIDER_DATA_PROP_SET_COUNT value
4119 if (scf_property_get_value(prop
, value
) == -1) {
4121 "get property value %s/%s failed - %s",
4122 pgName
, STMF_PROVIDER_DATA_PROP_SET_COUNT
,
4123 scf_strerror(scf_error()));
4124 ret
= STMF_PS_ERROR
;
4129 * Now get the actual value from the value handle
4130 * and set the caller's token
4132 if (scf_value_get_count(value
, setToken
) == -1) {
4134 "get integer value %s/%s failed - %s",
4135 pgName
, STMF_PROVIDER_DATA_PROP_SET_COUNT
,
4136 scf_strerror(scf_error()));
4137 ret
= STMF_PS_ERROR
;
4143 nvlistEncoded
= (char *)calloc(1,
4144 blockCnt
* STMF_PROVIDER_DATA_PROP_SIZE
);
4145 if (nvlistEncoded
== NULL
) {
4146 syslog(LOG_ERR
, "nvlistEncoded alloc failed");
4147 ret
= STMF_PS_ERROR_NOMEM
;
4151 for (i
= 0; i
< blockCnt
; i
++) {
4152 bzero(dataPropertyName
, sizeof (dataPropertyName
));
4154 * create the name to use for the property
4156 (void) snprintf(dataPropertyName
, sizeof (dataPropertyName
),
4157 "%s-%d", STMF_PROVIDER_DATA_PROP_PREFIX
, i
);
4159 if (scf_pg_get_property(pg
, dataPropertyName
, prop
) == -1) {
4160 syslog(LOG_ERR
, "get property %s/%s failed - %s",
4161 pgName
, dataPropertyName
,
4162 scf_strerror(scf_error()));
4163 ret
= STMF_PS_ERROR
;
4167 if (scf_property_get_value(prop
, value
) == -1) {
4168 syslog(LOG_ERR
, "get property value %s/%s failed - %s",
4169 pgName
, dataPropertyName
,
4170 scf_strerror(scf_error()));
4171 ret
= STMF_PS_ERROR
;
4176 * Set the data block offset
4178 blockOffset
= STMF_PROVIDER_DATA_PROP_SIZE
* i
;
4179 actualBlockSize
= scf_value_get_opaque(value
,
4180 &nvlistEncoded
[blockOffset
], STMF_PROVIDER_DATA_PROP_SIZE
);
4181 if (actualBlockSize
== -1) {
4182 syslog(LOG_ERR
, "get opaque property value %s/%s "
4183 "failed - %s", pgName
, dataPropertyName
,
4184 scf_strerror(scf_error()));
4185 ret
= STMF_PS_ERROR
;
4188 nvlistEncodedSize
+= actualBlockSize
;
4191 if (nvlist_unpack(nvlistEncoded
, nvlistEncodedSize
, nvl
, 0) != 0) {
4192 syslog(LOG_ERR
, "unable to unpack nvlist");
4193 ret
= STMF_PS_ERROR
;
4202 if (handle
!= NULL
) {
4203 scf_handle_destroy(handle
);
4206 scf_service_destroy(svc
);
4212 scf_property_destroy(prop
);
4214 if (value
!= NULL
) {
4215 scf_value_destroy(value
);
4217 if (nvlistEncoded
!= NULL
) {
4218 free(nvlistEncoded
);
4225 * psGetProviderDataList
4227 * Retrieves the list of providers that currently store persistent data
4229 * providerList - pointer to a pointer to an stmfProviderList structure
4230 * On success, this will contain the list of providers
4231 * currently storing persistent data.
4234 psGetProviderDataList(stmfProviderList
**providerList
)
4236 scf_handle_t
*handle
= NULL
;
4237 scf_service_t
*svc
= NULL
;
4238 scf_propertygroup_t
*pg
= NULL
;
4239 scf_property_t
*prop
= NULL
;
4240 scf_value_t
*value
= NULL
;
4241 scf_iter_t
*pgIter
= NULL
;
4242 char buf
[MAXNAMELEN
];
4243 int providerCnt
= 0;
4244 int64_t providerType
;
4246 int ret
= STMF_PS_SUCCESS
;
4248 ret
= iPsInit(&handle
, &svc
);
4249 if (ret
!= STMF_PS_SUCCESS
) {
4253 *providerList
= NULL
;
4256 * Allocate scf resources
4258 if (((pg
= scf_pg_create(handle
)) == NULL
) ||
4259 ((value
= scf_value_create(handle
)) == NULL
) ||
4260 ((prop
= scf_property_create(handle
)) == NULL
) ||
4261 ((pgIter
= scf_iter_create(handle
)) == NULL
)) {
4262 syslog(LOG_ERR
, "scf alloc resource failed - %s",
4263 scf_strerror(scf_error()));
4264 ret
= STMF_PS_ERROR
;
4269 * pgIter is the iterator handle
4271 if (scf_iter_service_pgs(pgIter
, svc
) == -1) {
4272 syslog(LOG_ERR
, "iter property groups failed - %s",
4273 scf_strerror(scf_error()));
4274 ret
= STMF_PS_ERROR
;
4278 while (scf_iter_next_pg(pgIter
, pg
) == 1) {
4279 if (scf_pg_get_name(pg
, buf
, sizeof (buf
)) == -1) {
4280 syslog(LOG_ERR
, "get name failed - %s",
4281 scf_strerror(scf_error()));
4282 ret
= STMF_PS_ERROR
;
4286 * Only count LU property groups
4288 if (strncmp(buf
, STMF_PROVIDER_DATA_PREFIX
,
4289 strlen(STMF_PROVIDER_DATA_PREFIX
)) == 0) {
4295 * pgIter is the iterator handle
4297 if (scf_iter_service_pgs(pgIter
, svc
) == -1) {
4298 syslog(LOG_ERR
, "iter property groups failed - %s",
4299 scf_strerror(scf_error()));
4300 ret
= STMF_PS_ERROR
;
4304 *providerList
= (stmfProviderList
*)calloc(1,
4305 sizeof (stmfProviderList
) + providerCnt
* sizeof (stmfProvider
));
4306 if (*providerList
== NULL
) {
4307 ret
= STMF_PS_ERROR_NOMEM
;
4312 * it's possible for entries to be added/removed while we're retrieving
4313 * the property groups. Just make sure we don't write beyond our
4314 * allocated buffer by checking to ensure i < providerCnt.
4316 while ((scf_iter_next_pg(pgIter
, pg
) == 1) && (i
< providerCnt
)) {
4317 if (scf_pg_get_name(pg
, buf
, sizeof (buf
)) == -1) {
4318 syslog(LOG_ERR
, "get name failed - %s",
4319 scf_strerror(scf_error()));
4320 ret
= STMF_PS_ERROR
;
4324 * Only use provider data property groups
4326 if (strncmp(buf
, STMF_PROVIDER_DATA_PREFIX
,
4327 strlen(STMF_PROVIDER_DATA_PREFIX
)) != 0) {
4332 * Get the STMF_PROVIDER_DATA_PROP_TYPE property
4334 if (scf_pg_get_property(pg
, STMF_PROVIDER_DATA_PROP_TYPE
,
4336 syslog(LOG_ERR
, "get property %s/%s failed - %s",
4337 buf
, STMF_PROVIDER_DATA_PROP_TYPE
,
4338 scf_strerror(scf_error()));
4339 ret
= STMF_PS_ERROR
;
4344 * Get the STMF_PROVIDER_DATA_PROP_TYPE value
4346 if (scf_property_get_value(prop
, value
) == -1) {
4347 syslog(LOG_ERR
, "get property value %s/%s failed - %s",
4348 buf
, STMF_PROVIDER_DATA_PROP_TYPE
,
4349 scf_strerror(scf_error()));
4350 ret
= STMF_PS_ERROR
;
4355 * Now get the actual value from the value handle
4357 if (scf_value_get_integer(value
, &providerType
) == -1) {
4358 syslog(LOG_ERR
, "get integer value %s/%s failed - %s",
4359 buf
, STMF_PROVIDER_DATA_PROP_TYPE
,
4360 scf_strerror(scf_error()));
4361 ret
= STMF_PS_ERROR
;
4365 (*providerList
)->provider
[i
].providerType
= providerType
;
4367 /* determine offset for copy of provider name */
4368 j
= strlen(STMF_PROVIDER_DATA_PREFIX
);
4370 /* copy provider name to caller's list */
4371 (void) strncpy((*providerList
)->provider
[i
].name
, buf
+ j
,
4372 sizeof ((*providerList
)->provider
[i
].name
));
4374 (*providerList
)->cnt
++;
4377 if (ret
!= STMF_PS_SUCCESS
) {
4378 free(*providerList
);
4386 if (handle
!= NULL
) {
4387 scf_handle_destroy(handle
);
4390 scf_service_destroy(svc
);
4395 if (value
!= NULL
) {
4396 scf_value_destroy(value
);
4399 scf_property_destroy(prop
);
4401 if (pgIter
!= NULL
) {
4402 scf_iter_destroy(pgIter
);
4412 * Stores a packed nvlist on a per provider basis
4414 * providerName - property group name to use
4415 * nvl - nvlist to store
4416 * providerType - type of provider (logical unit or port)
4420 psSetProviderData(char *providerName
, nvlist_t
*nvl
, int providerType
,
4423 scf_handle_t
*handle
= NULL
;
4424 scf_service_t
*svc
= NULL
;
4425 scf_propertygroup_t
*pg
= NULL
;
4426 scf_property_t
*prop
= NULL
;
4427 scf_transaction_t
*tran
= NULL
;
4428 /* represents arrays of entry and value pointers for scf */
4429 scf_transaction_entry_t
**addEntry
= NULL
;
4430 scf_transaction_entry_t
**deleteEntry
= NULL
;
4431 scf_value_t
**addValue
= NULL
;
4434 * These declarations are for known entry and value set/get
4437 scf_transaction_entry_t
*entry1
= NULL
;
4438 scf_transaction_entry_t
*entry2
= NULL
;
4439 scf_transaction_entry_t
*entry3
= NULL
;
4440 scf_transaction_entry_t
*entry5
= NULL
;
4441 scf_value_t
*value1
= NULL
;
4442 scf_value_t
*value2
= NULL
;
4443 scf_value_t
*value3
= NULL
;
4444 scf_value_t
*value4
= NULL
;
4445 scf_value_t
*value5
= NULL
;
4447 boolean_t newPg
= B_FALSE
;
4448 char pgName
[MAXPATHLEN
];
4449 char dataPropertyName
[STMF_PROVIDER_DATA_PROP_NAME_SIZE
];
4450 char *nvlistEncoded
= NULL
;
4451 size_t nvlistEncodedSize
;
4454 int addEntryAlloc
= 0, deleteEntryAlloc
= 0, addValueAlloc
= 0;
4456 uint64_t oldBlockCnt
= 0;
4457 uint64_t blockCnt
= 0;
4458 uint64_t setCnt
= 0;
4459 boolean_t foundSetCnt
= B_TRUE
;
4460 int ret
= STMF_PS_SUCCESS
;
4463 if (providerName
== NULL
|| (providerType
!= STMF_LU_PROVIDER_TYPE
&&
4464 providerType
!= STMF_PORT_PROVIDER_TYPE
)) {
4465 ret
= STMF_PS_ERROR_INVALID_ARG
;
4469 ret
= iPsInit(&handle
, &svc
);
4470 if (ret
!= STMF_PS_SUCCESS
) {
4474 bzero(pgName
, sizeof (pgName
));
4476 * create the property group name
4478 (void) snprintf(pgName
, sizeof (pgName
), "%s%s",
4479 STMF_PROVIDER_DATA_PREFIX
, providerName
);
4482 * Allocate scf resources
4484 if (((pg
= scf_pg_create(handle
)) == NULL
) ||
4485 ((entry1
= scf_entry_create(handle
)) == NULL
) ||
4486 ((entry2
= scf_entry_create(handle
)) == NULL
) ||
4487 ((entry3
= scf_entry_create(handle
)) == NULL
) ||
4488 ((entry5
= scf_entry_create(handle
)) == NULL
) ||
4489 ((value1
= scf_value_create(handle
)) == NULL
) ||
4490 ((value2
= scf_value_create(handle
)) == NULL
) ||
4491 ((value3
= scf_value_create(handle
)) == NULL
) ||
4492 ((value4
= scf_value_create(handle
)) == NULL
) ||
4493 ((value5
= scf_value_create(handle
)) == NULL
) ||
4494 ((prop
= scf_property_create(handle
)) == NULL
) ||
4495 ((tran
= scf_transaction_create(handle
)) == NULL
)) {
4496 syslog(LOG_ERR
, "scf alloc resource failed - %s",
4497 scf_strerror(scf_error()));
4498 ret
= STMF_PS_ERROR
;
4503 * Get the existing property group
4505 if (scf_service_get_pg(svc
, pgName
, pg
) == -1) {
4506 if (scf_error() != SCF_ERROR_NOT_FOUND
) {
4507 syslog(LOG_ERR
, "get pg %s failed - %s",
4508 pgName
, scf_strerror(scf_error()));
4509 ret
= STMF_PS_ERROR
;
4513 * create the property group.
4515 if (scf_service_add_pg(svc
, pgName
,
4516 SCF_GROUP_APPLICATION
, 0, pg
) == -1) {
4517 syslog(LOG_ERR
, "add pg %s failed - %s",
4518 pgName
, scf_strerror(scf_error()));
4519 ret
= STMF_PS_ERROR
;
4527 * Begin the transaction
4529 if (scf_transaction_start(tran
, pg
) == -1) {
4530 syslog(LOG_ERR
, "start transaction for %s failed - %s",
4531 pgName
, scf_strerror(scf_error()));
4532 ret
= STMF_PS_ERROR
;
4538 * Get the STMF_PROVIDER_DATA_PROP_COUNT property
4540 if (scf_pg_get_property(pg
, STMF_PROVIDER_DATA_PROP_COUNT
,
4542 syslog(LOG_ERR
, "get property %s/%s failed - %s",
4543 pgName
, STMF_PROVIDER_DATA_PROP_COUNT
,
4544 scf_strerror(scf_error()));
4545 ret
= STMF_PS_ERROR
;
4550 * Get the STMF_PROVIDER_DATA_PROP_COUNT value
4552 if (scf_property_get_value(prop
, value4
) == -1) {
4553 syslog(LOG_ERR
, "get property value %s/%s failed - %s",
4554 pgName
, STMF_PROVIDER_DATA_PROP_COUNT
,
4555 scf_strerror(scf_error()));
4556 ret
= STMF_PS_ERROR
;
4561 * Now get the actual value from the value handle
4563 if (scf_value_get_count(value4
, &oldBlockCnt
) == -1) {
4564 syslog(LOG_ERR
, "get integer value %s/%s failed - %s",
4565 pgName
, STMF_PROVIDER_DATA_PROP_COUNT
,
4566 scf_strerror(scf_error()));
4567 ret
= STMF_PS_ERROR
;
4573 * Get the STMF_PROVIDER_DATA_PROP_SET_COUNT property
4574 * If it doesn't exist, we'll create it later after successfully
4577 if (scf_pg_get_property(pg
, STMF_PROVIDER_DATA_PROP_SET_COUNT
,
4579 if (scf_error() == SCF_ERROR_NOT_FOUND
) {
4580 foundSetCnt
= B_FALSE
;
4582 syslog(LOG_ERR
, "get property %s/%s failed - %s",
4583 pgName
, STMF_PROVIDER_DATA_PROP_SET_COUNT
,
4584 scf_strerror(scf_error()));
4585 ret
= STMF_PS_ERROR
;
4592 * Get the STMF_PROVIDER_DATA_PROP_SET_COUNT value
4594 if (scf_property_get_value(prop
, value5
) == -1) {
4595 syslog(LOG_ERR
, "get property value %s/%s failed - %s",
4596 pgName
, STMF_PROVIDER_DATA_PROP_SET_COUNT
,
4597 scf_strerror(scf_error()));
4598 ret
= STMF_PS_ERROR
;
4603 * Now get the actual value from the value handle
4605 if (scf_value_get_count(value5
, &setCnt
) == -1) {
4606 syslog(LOG_ERR
, "get integer value %s/%s failed - %s",
4607 pgName
, STMF_PROVIDER_DATA_PROP_SET_COUNT
,
4608 scf_strerror(scf_error()));
4609 ret
= STMF_PS_ERROR
;
4614 * Compare the setCnt prop to the caller's.
4616 if (setToken
&& (*setToken
!= setCnt
)) {
4617 ret
= STMF_PS_ERROR_PROV_DATA_STALE
;
4625 * prepare the list for writing
4627 if (nvlist_pack(nvl
, &nvlistEncoded
, &nvlistEncodedSize
,
4628 NV_ENCODE_XDR
, 0) != 0) {
4629 syslog(LOG_ERR
, "nvlist_pack for %s failed",
4631 ret
= STMF_PS_ERROR_NOMEM
;
4635 /* Determine how many chunks we need to write */
4636 blockCnt
= nvlistEncodedSize
/STMF_PROVIDER_DATA_PROP_SIZE
;
4637 if (nvlistEncodedSize
% STMF_PROVIDER_DATA_PROP_SIZE
)
4640 /* allocate entry and value resources for writing those chunks */
4641 addEntry
= (scf_transaction_entry_t
**)calloc(1, sizeof (*addEntry
)
4643 if (addEntry
== NULL
) {
4644 syslog(LOG_ERR
, "addEntry alloc for %s failed", pgName
);
4645 ret
= STMF_PS_ERROR_NOMEM
;
4649 addValue
= (scf_value_t
**)calloc(1, sizeof (*addValue
)
4651 if (addValue
== NULL
) {
4652 syslog(LOG_ERR
, "value alloc for %s failed", pgName
);
4653 ret
= STMF_PS_ERROR_NOMEM
;
4658 * allocate entry delete resources for deleting anything existing
4659 * that is more than the new block count. We could leave them around
4660 * without suffering any ill effects but it will be cleaner to look at
4661 * in smf tools if they are deleted.
4663 if (oldBlockCnt
> blockCnt
) {
4664 deleteEntry
= (scf_transaction_entry_t
**)calloc(1,
4665 sizeof (*deleteEntry
) * (oldBlockCnt
- blockCnt
));
4666 if (deleteEntry
== NULL
) {
4667 syslog(LOG_ERR
, "deleteEntry alloc for %s failed",
4669 ret
= STMF_PS_ERROR_NOMEM
;
4672 deleteEntryAlloc
= oldBlockCnt
- blockCnt
;
4676 for (i
= 0; i
< blockCnt
; i
++) {
4678 * Create the entry resource for the prop
4680 addEntry
[i
] = scf_entry_create(handle
);
4681 if (addEntry
[i
] == NULL
) {
4682 syslog(LOG_ERR
, "scf value alloc for %s failed - %s",
4683 pgName
, scf_strerror(scf_error()));
4684 ret
= STMF_PS_ERROR
;
4688 /* bump alloc count for addEntry allocation */
4692 * create the name to use for the property
4694 (void) snprintf(dataPropertyName
, sizeof (dataPropertyName
),
4695 "%s-%d", STMF_PROVIDER_DATA_PROP_PREFIX
, i
);
4698 * Create the new property
4700 if (scf_transaction_property_new(tran
, addEntry
[i
],
4701 dataPropertyName
, SCF_TYPE_OPAQUE
) == -1) {
4702 if (scf_error() == SCF_ERROR_EXISTS
) {
4703 if (scf_transaction_property_change(tran
,
4704 addEntry
[i
], dataPropertyName
,
4705 SCF_TYPE_OPAQUE
) == -1) {
4706 syslog(LOG_ERR
, "transaction property "
4707 "change %s/%s failed - %s",
4708 pgName
, dataPropertyName
,
4709 scf_strerror(scf_error()));
4710 ret
= STMF_PS_ERROR
;
4715 "transaction property new %s/%s "
4716 "failed - %s", pgName
, dataPropertyName
,
4717 scf_strerror(scf_error()));
4718 ret
= STMF_PS_ERROR
;
4723 * Create the value resource for the prop
4725 addValue
[i
] = scf_value_create(handle
);
4726 if (addValue
[i
] == NULL
) {
4727 syslog(LOG_ERR
, "scf value alloc for %s failed - %s",
4728 pgName
, scf_strerror(scf_error()));
4729 ret
= STMF_PS_ERROR
;
4733 /* bump alloc count for addValue allocation */
4737 * Set the data block offset and size
4739 if ((STMF_PROVIDER_DATA_PROP_SIZE
* (i
+ 1))
4740 > nvlistEncodedSize
) {
4741 blockSize
= nvlistEncodedSize
4742 - STMF_PROVIDER_DATA_PROP_SIZE
* i
;
4744 blockSize
= STMF_PROVIDER_DATA_PROP_SIZE
;
4747 blockOffset
= STMF_PROVIDER_DATA_PROP_SIZE
* i
;
4748 if (scf_value_set_opaque(addValue
[i
],
4749 &nvlistEncoded
[blockOffset
], blockSize
) == -1) {
4750 syslog(LOG_ERR
, "set value for %s failed - %s",
4751 pgName
, scf_strerror(scf_error()));
4752 ret
= STMF_PS_ERROR
;
4757 * Add the data block to the transaction entry
4759 if (scf_entry_add_value(addEntry
[i
], addValue
[i
]) == -1) {
4760 syslog(LOG_ERR
, "add value for %s failed - %s",
4761 pgName
, scf_strerror(scf_error()));
4762 ret
= STMF_PS_ERROR
;
4768 * Now we need to delete any chunks (properties) that are no longer
4769 * needed. Iterate through the rest of the chunks deleting each.
4771 for (i
= blockCnt
; i
< oldBlockCnt
; i
++) {
4773 * Create the entry resource for the prop
4775 deleteEntry
[j
] = scf_entry_create(handle
);
4776 if (deleteEntry
[j
] == NULL
) {
4777 syslog(LOG_ERR
, "scf value alloc for %s failed - %s",
4778 pgName
, scf_strerror(scf_error()));
4779 ret
= STMF_PS_ERROR
;
4784 * create the name to use for the property
4786 (void) snprintf(dataPropertyName
, sizeof (dataPropertyName
),
4787 "%s-%d", STMF_PROVIDER_DATA_PROP_PREFIX
, i
);
4790 * Delete the existing property
4792 if (scf_transaction_property_delete(tran
, deleteEntry
[j
++],
4793 dataPropertyName
) == -1) {
4794 syslog(LOG_ERR
, "delete property %s/%s failed - %s",
4795 pgName
, dataPropertyName
,
4796 scf_strerror(scf_error()));
4797 ret
= STMF_PS_ERROR
;
4804 * Ensure the read_authorization property is set
4807 if (scf_transaction_property_new(tran
, entry1
,
4808 "read_authorization", SCF_TYPE_ASTRING
) == -1) {
4809 syslog(LOG_ERR
, "transaction property %s/%s new "
4810 "failed - %s", pgName
, "read_authorization",
4811 scf_strerror(scf_error()));
4812 ret
= STMF_PS_ERROR
;
4816 if (scf_value_set_astring(value1
, STMF_SMF_READ_ATTR
) == -1) {
4817 syslog(LOG_ERR
, "set value %s/%s failed - %s",
4818 pgName
, "read_authorization",
4819 scf_strerror(scf_error()));
4820 ret
= STMF_PS_ERROR
;
4824 if (scf_entry_add_value(entry1
, value1
) == -1) {
4825 syslog(LOG_ERR
, "add value %s/%s failed - %s",
4826 pgName
, "read_authorization",
4827 scf_strerror(scf_error()));
4828 ret
= STMF_PS_ERROR
;
4833 /* create or change the count property */
4834 if (scf_transaction_property_new(tran
, entry2
,
4835 STMF_PROVIDER_DATA_PROP_COUNT
, SCF_TYPE_COUNT
) == -1) {
4836 if (scf_error() == SCF_ERROR_EXISTS
) {
4837 if (scf_transaction_property_change(tran
, entry2
,
4838 STMF_PROVIDER_DATA_PROP_COUNT
,
4839 SCF_TYPE_COUNT
) == -1) {
4840 syslog(LOG_ERR
, "transaction property change "
4841 "%s/%s failed - %s", pgName
,
4842 STMF_PROVIDER_DATA_PROP_COUNT
,
4843 scf_strerror(scf_error()));
4844 ret
= STMF_PS_ERROR
;
4848 syslog(LOG_ERR
, "transaction property %s/%s new "
4849 "failed - %s", pgName
,
4850 STMF_PROVIDER_DATA_PROP_COUNT
,
4851 scf_strerror(scf_error()));
4852 ret
= STMF_PS_ERROR
;
4857 scf_value_set_count(value2
, blockCnt
);
4859 if (scf_entry_add_value(entry2
, value2
) == -1) {
4860 syslog(LOG_ERR
, "add value %s/%s failed - %s",
4861 pgName
, STMF_PROVIDER_DATA_PROP_COUNT
,
4862 scf_strerror(scf_error()));
4863 ret
= STMF_PS_ERROR
;
4867 /* create or change the set count property */
4868 if (scf_transaction_property_new(tran
, entry5
,
4869 STMF_PROVIDER_DATA_PROP_SET_COUNT
, SCF_TYPE_COUNT
) == -1) {
4870 if (scf_error() == SCF_ERROR_EXISTS
) {
4871 if (scf_transaction_property_change(tran
, entry5
,
4872 STMF_PROVIDER_DATA_PROP_SET_COUNT
,
4873 SCF_TYPE_COUNT
) == -1) {
4875 "transaction property change %s/%s "
4876 "failed - %s", pgName
,
4877 STMF_PROVIDER_DATA_PROP_SET_COUNT
,
4878 scf_strerror(scf_error()));
4879 ret
= STMF_PS_ERROR
;
4883 syslog(LOG_ERR
, "transaction property new %s/%s "
4884 "failed - %s", pgName
,
4885 STMF_PROVIDER_DATA_PROP_SET_COUNT
,
4886 scf_strerror(scf_error()));
4887 ret
= STMF_PS_ERROR
;
4894 scf_value_set_count(value5
, setCnt
);
4896 if (scf_entry_add_value(entry5
, value5
) == -1) {
4897 syslog(LOG_ERR
, "add value %s/%s failed - %s",
4898 pgName
, STMF_PROVIDER_DATA_PROP_SET_COUNT
,
4899 scf_strerror(scf_error()));
4900 ret
= STMF_PS_ERROR
;
4904 /* create or change the provider type property */
4905 if (scf_transaction_property_new(tran
, entry3
,
4906 STMF_PROVIDER_DATA_PROP_TYPE
, SCF_TYPE_INTEGER
) == -1) {
4907 if (scf_error() == SCF_ERROR_EXISTS
) {
4908 if (scf_transaction_property_change(tran
, entry3
,
4909 STMF_PROVIDER_DATA_PROP_TYPE
,
4910 SCF_TYPE_INTEGER
) == -1) {
4912 "transaction property change %s/%s "
4913 "failed - %s", pgName
,
4914 STMF_PROVIDER_DATA_PROP_TYPE
,
4915 scf_strerror(scf_error()));
4916 ret
= STMF_PS_ERROR
;
4920 syslog(LOG_ERR
, "transaction property new %s/%s "
4921 "failed - %s", pgName
, STMF_PROVIDER_DATA_PROP_TYPE
,
4922 scf_strerror(scf_error()));
4923 ret
= STMF_PS_ERROR
;
4928 switch (providerType
) {
4929 case STMF_PORT_PROVIDER_TYPE
:
4930 case STMF_LU_PROVIDER_TYPE
:
4931 scf_value_set_integer(value3
, providerType
);
4934 ret
= STMF_PS_ERROR
;
4938 if (scf_entry_add_value(entry3
, value3
) == -1) {
4939 syslog(LOG_ERR
, "add value %s/%s failed - %s", pgName
,
4940 STMF_PROVIDER_DATA_PROP_TYPE
, scf_strerror(scf_error()));
4941 ret
= STMF_PS_ERROR
;
4946 if ((commitRet
= scf_transaction_commit(tran
)) != 1) {
4947 syslog(LOG_ERR
, "transaction commit for %s failed - %s",
4948 pgName
, scf_strerror(scf_error()));
4949 if (commitRet
== 0) {
4950 ret
= STMF_PS_ERROR_BUSY
;
4952 ret
= STMF_PS_ERROR
;
4957 /* pass the new token back to the caller if requested */
4958 if (ret
== STMF_PS_SUCCESS
&& setToken
) {
4966 if (handle
!= NULL
) {
4967 scf_handle_destroy(handle
);
4970 scf_service_destroy(svc
);
4976 scf_property_destroy(prop
);
4979 scf_transaction_destroy(tran
);
4981 for (i
= 0; i
< addEntryAlloc
; i
++) {
4982 scf_entry_destroy(addEntry
[i
]);
4984 for (i
= 0; i
< addValueAlloc
; i
++) {
4985 scf_value_destroy(addValue
[i
]);
4989 for (i
= 0; i
< deleteEntryAlloc
; i
++) {
4990 scf_entry_destroy(deleteEntry
[i
]);
4993 if (entry1
!= NULL
) {
4994 scf_entry_destroy(entry1
);
4996 if (entry2
!= NULL
) {
4997 scf_entry_destroy(entry2
);
4999 if (entry3
!= NULL
) {
5000 scf_entry_destroy(entry3
);
5002 if (entry5
!= NULL
) {
5003 scf_entry_destroy(entry5
);
5005 if (value1
!= NULL
) {
5006 scf_value_destroy(value1
);
5008 if (value2
!= NULL
) {
5009 scf_value_destroy(value2
);
5011 if (value3
!= NULL
) {
5012 scf_value_destroy(value3
);
5014 if (value4
!= NULL
) {
5015 scf_value_destroy(value4
);
5017 if (value5
!= NULL
) {
5018 scf_value_destroy(value5
);
5020 if (nvlistEncoded
!= NULL
) {
5021 free(nvlistEncoded
);
5030 * Purpose: Get a single view entry based on the logical unit identifier and
5033 * lu - logical unit identifier
5034 * viewEntryIndex - index of view entry
5035 * ve - caller allocated stmfViewEntry structure. On success, this will
5036 * contain the retrieved view entry
5039 psGetViewEntry(stmfGuid
*lu
, uint32_t viewEntryIndex
, stmfViewEntry
*ve
)
5041 scf_handle_t
*handle
= NULL
;
5042 scf_service_t
*svc
= NULL
;
5043 scf_propertygroup_t
*pg
= NULL
;
5044 char guidAsciiBuf
[33]; /* size of ascii hex 16 byte guid with NULL */
5045 char viewEntryPgName
[VIEW_ENTRY_PG_SIZE
];
5046 char luPgName
[LOGICAL_UNIT_PG_SIZE
];
5047 int ret
= STMF_PS_SUCCESS
;
5049 ret
= iPsInit(&handle
, &svc
);
5050 if (ret
!= STMF_PS_SUCCESS
) {
5054 pg
= scf_pg_create(handle
);
5056 syslog(LOG_ERR
, "scf pg alloc failed - %s",
5057 scf_strerror(scf_error()));
5058 ret
= STMF_PS_ERROR
;
5062 /* Convert to ASCII uppercase hexadecimal string */
5063 (void) snprintf(guidAsciiBuf
, sizeof (guidAsciiBuf
),
5064 "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
5065 lu
->guid
[0], lu
->guid
[1], lu
->guid
[2], lu
->guid
[3], lu
->guid
[4],
5066 lu
->guid
[5], lu
->guid
[6], lu
->guid
[7], lu
->guid
[8], lu
->guid
[9],
5067 lu
->guid
[10], lu
->guid
[11], lu
->guid
[12], lu
->guid
[13],
5068 lu
->guid
[14], lu
->guid
[15]);
5070 (void) snprintf(luPgName
, sizeof (luPgName
), "%s-%s",
5071 STMF_LU_PREFIX
, guidAsciiBuf
);
5074 * Format of view entry property group name:
5075 * VE-<view_entry_index>-<lu_name>
5077 (void) snprintf(viewEntryPgName
, sizeof (viewEntryPgName
),
5078 "%s-%d-%s", STMF_VE_PREFIX
, viewEntryIndex
, guidAsciiBuf
);
5080 if (scf_service_get_pg(svc
, viewEntryPgName
, pg
) == -1) {
5081 if (scf_error() == SCF_ERROR_NOT_FOUND
) {
5082 ret
= STMF_PS_ERROR_NOT_FOUND
;
5084 syslog(LOG_ERR
, "get pg %s failed - %s",
5085 viewEntryPgName
, scf_strerror(scf_error()));
5086 ret
= STMF_PS_ERROR
;
5092 if ((ret
= iPsGetViewEntry(viewEntryPgName
, ve
)) != STMF_PS_SUCCESS
) {
5093 ret
= STMF_PS_ERROR
;
5101 if (handle
!= NULL
) {
5102 scf_handle_destroy(handle
);
5105 scf_service_destroy(svc
);
5117 * Remove a view entry
5119 * luGuid - identifier of logical unit from which to remove view entry
5120 * viewEntryIndex - view entry name to remove
5123 * STMF_PS_SUCCESS on success
5124 * STMF_PS_ERROR_* on failure
5127 psRemoveViewEntry(stmfGuid
*lu
, uint32_t viewEntryIndex
)
5129 scf_handle_t
*handle
= NULL
;
5130 scf_service_t
*svc
= NULL
;
5131 scf_propertygroup_t
*pg
= NULL
;
5132 char guidAsciiBuf
[33]; /* size of ascii hex 16 byte guid with NULL */
5133 char viewEntryPgName
[VIEW_ENTRY_PG_SIZE
];
5134 char luPgName
[LOGICAL_UNIT_PG_SIZE
];
5135 int ret
= STMF_PS_SUCCESS
;
5136 sigset_t sigmaskRestore
;
5138 /* grab the signal hold lock */
5139 (void) pthread_mutex_lock(&sigSetLock
);
5142 * hold signals until we're done
5144 if (holdSignal(&sigmaskRestore
) != 0) {
5145 (void) pthread_mutex_unlock(&sigSetLock
);
5146 return (STMF_PS_ERROR
);
5149 ret
= iPsInit(&handle
, &svc
);
5150 if (ret
!= STMF_PS_SUCCESS
) {
5154 pg
= scf_pg_create(handle
);
5156 syslog(LOG_ERR
, "scf pg alloc failed - %s",
5157 scf_strerror(scf_error()));
5158 ret
= STMF_PS_ERROR
;
5162 /* Convert to ASCII uppercase hexadecimal string */
5163 (void) snprintf(guidAsciiBuf
, sizeof (guidAsciiBuf
),
5164 "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
5165 lu
->guid
[0], lu
->guid
[1], lu
->guid
[2], lu
->guid
[3], lu
->guid
[4],
5166 lu
->guid
[5], lu
->guid
[6], lu
->guid
[7], lu
->guid
[8], lu
->guid
[9],
5167 lu
->guid
[10], lu
->guid
[11], lu
->guid
[12], lu
->guid
[13],
5168 lu
->guid
[14], lu
->guid
[15]);
5170 (void) snprintf(luPgName
, sizeof (luPgName
), "%s-%s",
5171 STMF_LU_PREFIX
, guidAsciiBuf
);
5174 * Format of view entry property group name:
5175 * VE-<view_entry_index>-<lu_name>
5177 (void) snprintf(viewEntryPgName
, sizeof (viewEntryPgName
),
5178 "%s-%d-%s", STMF_VE_PREFIX
, viewEntryIndex
, guidAsciiBuf
);
5180 if (scf_service_get_pg(svc
, viewEntryPgName
, pg
) == -1) {
5181 if (scf_error() == SCF_ERROR_NOT_FOUND
) {
5182 ret
= STMF_PS_ERROR_NOT_FOUND
;
5184 syslog(LOG_ERR
, "get pg %s failed - %s",
5185 viewEntryPgName
, scf_strerror(scf_error()));
5186 ret
= STMF_PS_ERROR
;
5192 * update the logical unit property group to remove
5193 * the view entry and update the view entry count
5194 * If it fails, we won't delete the property group so that
5195 * we maintain consistency.
5197 if ((ret
= iPsAddRemoveLuViewEntry(luPgName
, viewEntryPgName
,
5198 REMOVE
)) != STMF_PS_SUCCESS
) {
5203 * Delete the view entry. If this fails, we should try to add
5204 * the logical unit view entry property group back otherwise
5205 * we're inconsistent.
5207 if (scf_pg_delete(pg
) == -1) {
5208 syslog(LOG_ERR
, "delete pg %s failed - %s", viewEntryPgName
,
5209 scf_strerror(scf_error()));
5210 if ((ret
= iPsAddRemoveLuViewEntry(luPgName
, viewEntryPgName
,
5211 ADD
)) != STMF_PS_SUCCESS
) {
5212 syslog(LOG_ERR
, "add of view entry %s failed, possible"
5213 "inconsistency - %s", viewEntryPgName
,
5214 scf_strerror(scf_error()));
5216 ret
= STMF_PS_ERROR
;
5222 * Okay, we're done. Release the signals
5224 if (releaseSignal(&sigmaskRestore
) != 0) {
5226 * Don't set this as an STMF_PS_ERROR_*. We succeeded
5227 * the requested operation. But we do need to log it.
5229 syslog(LOG_ERR
, "Unable to release one or more signals - %s",
5236 if (handle
!= NULL
) {
5237 scf_handle_destroy(handle
);
5240 scf_service_destroy(svc
);
5246 /* release the signal hold lock */
5247 (void) pthread_mutex_unlock(&sigSetLock
);
5257 * Hold SIGINT, SIGTERM, SIGQUIT until further notice.
5259 * Saves old signal mask on a per thread basis
5260 * and saves action for the process.
5262 * Installs action for above signals.
5264 * locks held: sigSetLock
5268 * non-zero otherwise
5271 holdSignal(sigset_t
*sigmaskRestore
)
5273 struct sigaction act
;
5277 * Return existing signal mask for this thread
5279 if (pthread_sigmask(0, NULL
, sigmaskRestore
) != 0) {
5283 (void) sigemptyset(&act
.sa_mask
);
5284 act
.sa_handler
= sigHandler
;
5288 * Have we set the actions for the signals we want to catch?
5291 if (sigaction(SIGQUIT
, &act
, ¤tActionQuit
) != 0) {
5295 if (sigaction(SIGINT
, &act
, ¤tActionInt
) != 0) {
5299 if (sigaction(SIGTERM
, &act
, ¤tActionTerm
) != 0) {
5307 * We still need to change the mask for the current thread
5309 if (sigfillset(&sigmask
) != 0) {
5313 (void) sigdelset(&sigmask
, SIGQUIT
);
5315 (void) sigdelset(&sigmask
, SIGINT
);
5317 (void) sigdelset(&sigmask
, SIGTERM
);
5319 if (pthread_sigmask(SIG_SETMASK
, &sigmask
, NULL
) != 0) {
5329 * Re-install the original signal mask and signal actions
5331 * Also, raise any signals that were caught during the hold period and clear
5332 * the signal from the caught set (signalsCaught).
5334 * locks held: sigSetLock
5338 * non-zero otherwise
5341 releaseSignal(sigset_t
*sigmaskRestore
)
5345 if (sigaction(SIGQUIT
, ¤tActionQuit
, NULL
) != 0) {
5349 if (sigaction(SIGINT
, ¤tActionInt
, NULL
) != 0) {
5353 if (sigaction(SIGTERM
, ¤tActionTerm
, NULL
) != 0) {
5357 actionSet
= B_FALSE
;
5360 * Restore previous signal mask for this thread
5362 if (pthread_sigmask(SIG_SETMASK
, sigmaskRestore
, NULL
) != 0) {
5363 syslog(LOG_ERR
, "Unable to restore sigmask");
5367 * Now raise signals that were raised while we were held
5369 if (sigismember(&signalsCaught
, SIGTERM
)) {
5370 (void) sigdelset(&signalsCaught
, SIGTERM
);
5371 (void) raise(SIGTERM
);
5374 if (sigismember(&signalsCaught
, SIGINT
)) {
5375 (void) sigdelset(&signalsCaught
, SIGINT
);
5376 (void) raise(SIGINT
);
5379 if (sigismember(&signalsCaught
, SIGQUIT
)) {
5380 (void) sigdelset(&signalsCaught
, SIGQUIT
);
5381 (void) raise(SIGQUIT
);