/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
#include <libscf.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <assert.h>
#include <strings.h>
#include <libstmf.h>
#include <libstmf_impl.h>
#include <store.h>
#include <syslog.h>
#include <signal.h>
#include <pthread.h>
#include <libnvpair.h>
#include <limits.h>
#include <unistd.h>
/*
* This file's functions are responsible for all store and retrieve operations
* against the STMF smf(5) database. The following shows the currently defined
* schema for the STMF database:
*
*
* Stability: Volatile
*
* 1. Property Group: host_groups
* Properties: group_name-<N> where <N> is an unsigned integer
* type: ustring
* contains: group name
* group_name-<N>-member_list where <N> is an unsigned
* integer matching a group_name-<N> property.
* type: ustring
* contains: list of members
*
* Description:
* Contains the host group names as well as the host group members
* for each host group.
*
* 2. Property Group: target_groups
* Properties: group_name-<N> where <N> is an unsigned integer
* type: ustring
* contains: group name
* group_name-<N>-member_list where <N> is an unsigned
* integer matching a group_name-<N> property.
* type: ustring
* contains: list of members
*
* Description:
* Contains the target group names as well as the target group
* members for each target group.
*
* 3. Property Group: lu-<GUID>
* where <GUID> is a 32 character hexadecimal string.
* Properties: ve_cnt
* type: count
* contains: the number of current view entries
* view-entry-<N>-<GUID> where <N> is an unsigned integer
* type: ustring
* contains: nothing. Used as reference to the view
* entry property group
*
* Description:
* Contains the references to each view entry. One lu-<GUID>
* property group will exist for each logical unit with 1 or more
* view entries.
* Potentially can hold any other data that can be managed on a per
* logical unit basis.
*
* 4. Property Group: view_entry-<N>-<GUID> (matches property in lu-<GUID>
* property group)
* Properties: all_hosts
* type: boolean
* contains: when true, the value of host_group is
* ignored
* all_targets
* type: boolean
* contains: when true, the value of target_group is
* ignored
* host_group
* type: ustring
* contains: host group for logical unit mapping and
* masking purposes
* target_group
* type: ustring
* contains: target group for logical unit mapping and
* masking purposes
* lu_nbr
* type: opaque
* contains: the 8-byte SCSI logical unit number for
* mapping and masking purposes
* Description:
* One "view_entry-<N>-<GUID>" property group will exist for each
* view entry in the system. This property group name maps
* directly to the "lu-<GUID>" property group with a matching
* <GUID>.
*
* 5. Property Group: provider_data_pg_<provider-name>
* where <provider-name> is the name of the provider
* registered with stmf.
* Properties: provider_data_prop-<N>
* where <N> is a sequential identifier for the data
* chunk.
* type: opaque
* contains: up to STMF_PROVIDER_DATA_PROP_SIZE bytes
* of nvlist packed data.
* provider_data_count
* type: count
* contains: the number of provider data chunks
* provider_data_type
* type: integer
* contains: STMF_PORT_PROVIDER_TYPE or
* STMF_LU_PROVIDER_TYPE
*
* Description:
* Holds the nvlist packed provider data set via
* stmfSetProviderData and retrieved via stmfGetProviderData. Data
* is stored in STMF_PROVIDER_DATA_PROP_SIZE chunks. On retrieve,
* these chunks are reassembled and unpacked.
*
*/
static int iPsCreateDeleteGroup(char *, char *, int);
static int iPsAddRemoveGroupMember(char *, char *, char *, int);
static int iPsGetGroupList(char *, stmfGroupList **);
static int iPsGetGroupMemberList(char *, char *, stmfGroupProperties **);
static int iPsAddViewEntry(char *, char *, stmfViewEntry *);
static int iPsAddRemoveLuViewEntry(char *, char *, int);
static int iPsGetViewEntry(char *, stmfViewEntry *);
static int iPsGetActualGroupName(char *, char *, char *);
int);
static int iPsGetSetStmfProp(int, char *, int);
static int viewEntryCompare(const void *, const void *);
static int holdSignal(sigset_t *);
static int releaseSignal(sigset_t *);
static void sigHandler();
/*
* Version info for the SMF schema
*/
/*
* Note: Do not change these property names and size values.
* They represent fields in the persistent config and once modified
* will have a nasty side effect of invalidating the existing store.
* If you do need to change them, you'll need to use the versioning above
* to retain backward compatiblity with the previous configuration schema.
*/
/* BEGIN STORE PROPERTY DEFINITIONS */
/*
* Property Group Names and prefixes
*/
/*
* Property names and prefix for logical unit property group
*/
/* Property names for stmf properties */
/*
* Property names for view entry
*/
/* Property group suffix for provider data */
/* END STORE PROPERTY DEFINITIONS */
/* service name */
/* limits and flag values */
#define ADD 0
#define GET 0
/*
* sigHandler
*
* Catch the signal and set the global signalsCaught to the signal received
*
* signalsCaught will be used by releaseSignal to raise this signal when
* we're done processing our critical code.
*
*/
static void
{
}
/*
* iPsAddRemoveGroupMember
*
* Add or remove a member for a given group
*
* pgName - Property group name
*
* returns:
* STMF_PS_SUCCESS on success
* STMF_PS_ERROR_* on failure
*/
static int
int addRemoveFlag)
{
int i = 0;
int lastAlloc;
int valueArraySize = 0;
int commitRet;
/*
* Init the service handle
*/
if (ret != STMF_PS_SUCCESS) {
goto out;
}
/*
* Allocate scf resources
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/*
* Get the service property group handle
*/
if (scf_error() == SCF_ERROR_NOT_FOUND) {
} else {
ret = STMF_PS_ERROR;
}
goto out;
}
/*
* Begin the transaction
*/
ret = STMF_PS_ERROR;
goto out;
}
/*
* We're changing an existing property by adding a propval
* There are no add semantics in libscf for a property value. We'll
* need to read in the current properties and apply them all to the
* set and then add the one we were asked to add or omit the one
* we were asked to remove.
*/
SCF_TYPE_USTRING) == -1) {
if (scf_error() == SCF_ERROR_NOT_FOUND) {
} else {
ret = STMF_PS_ERROR;
scf_strerror(scf_error()));
}
goto out;
}
/*
* Get the property handle
*/
ret = STMF_PS_ERROR;
goto out;
}
/*
* Value lookup is used to lookup the existing values
*/
if (valueLookup == NULL) {
ret = STMF_PS_ERROR;
goto out;
}
/*
* valueIter is the iterator handle, create the resource
*/
ret = STMF_PS_ERROR;
goto out;
}
/*
* Allocate value resource pointers.
* We need a value resource for each value as value pointers passed
* to libscf cannot be destroyed until the commit or destroy on the
* transaction is done.
*
* We're using GROUP_MEMBER_ALLOC initially. If it's not large
* enough, we'll realloc on the fly
*/
* (lastAlloc = GROUP_MEMBER_ALLOC));
goto out;
}
/*
* Iterate through the existing values
*/
ret = STMF_PS_ERROR;
break;
}
/*
* Check for existing
* If we're adding, it's an error
* If we're removing, we skip it and simply not
* add it to the set. Subtraction by omission.
*/
if (addRemoveFlag == ADD) {
break;
} else {
continue;
}
}
/*
* Create the value resource for this iteration
*/
ret = STMF_PS_ERROR;
break;
}
/*
* Set the value
*/
ret = STMF_PS_ERROR;
break;
}
/*
* Now add the value
*/
ret = STMF_PS_ERROR;
break;
}
i++;
/*
* realloc if we've hit the previous alloc size
*/
if (i >= lastAlloc) {
ret = STMF_PS_ERROR;
break;
}
}
}
/*
* set valueArraySize to final allocated length
* so we can use it to destroy the resources correctly
*/
valueArraySize = i;
}
if (ret != STMF_PS_SUCCESS) {
goto out;
}
/*
* If we're adding, we have one more step. Add the member to the
* propval list
*/
if (addRemoveFlag == ADD) {
/*
* Now create the new entry
*/
ret = STMF_PS_ERROR;
goto out;
} else {
}
/*
* Set the new member name
*/
ret = STMF_PS_ERROR;
goto out;
}
/*
* Add the new member
*/
ret = STMF_PS_ERROR;
goto out;
}
}
/*
* Yes, we're finally done. We actually added or removed one entry
* from the list.
* Woohoo!
*/
if (commitRet == 0) {
} else {
ret = STMF_PS_ERROR;
}
goto out;
}
out:
/*
* Free resources
*/
}
}
}
}
}
}
if (valueLookup != NULL) {
}
}
/*
* Free valueSet scf resources
*/
if (valueArraySize > 0) {
for (i = 0; i < valueArraySize; i++) {
}
}
/*
* Now free the pointer array to the resources
*/
}
return (ret);
}
/*
* iPsAddRemoveLuViewEntry
*
* Adds or removes a view entry name property for a given logical unit
* property group. There is one logical unit property group for every logical
* unit that has one or more associated view entries.
*
* luPgName - Property group name of logical unit
* viewEntryPgName - Property group name of view entry
*
* returns:
* STMF_PS_SUCCESS on success
* STMF_PS_ERROR_* on failure
*/
static int
int addRemoveFlag)
{
int commitRet;
/*
* Init the service handle
*/
if (ret != STMF_PS_SUCCESS) {
goto out;
}
/*
* Allocate scf resources
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/* get the LU property group */
if (scf_error() == SCF_ERROR_NOT_FOUND &&
addRemoveFlag == ADD) {
/* if it doesn't exist, create it */
ret = STMF_PS_ERROR;
} else {
/* we need to create the VE_CNT property */
}
} else if (scf_error() == SCF_ERROR_NOT_FOUND) {
} else {
ret = STMF_PS_ERROR;
}
if (ret != STMF_PS_SUCCESS) {
goto out;
}
}
/*
* Begin the transaction
*/
ret = STMF_PS_ERROR;
goto out;
}
if (createVeCnt) {
/*
* Create the STMF_VE_CNT property. This will keep the current
* total view entries for this logical unit.
*/
SCF_TYPE_COUNT) == -1) {
if (scf_error() == SCF_ERROR_EXISTS) {
} else {
"transaction property new %s/%s "
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
}
goto out;
}
} else {
/*
* The STMF_VE_CNT property already exists. Just update
* it.
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/*
* Get the STMF_VE_CNT property
*/
ret = STMF_PS_ERROR;
goto out;
}
/*
* Get the STMF_VE_CNT value
*/
ret = STMF_PS_ERROR;
goto out;
}
/*
* Now get the actual value from the value handle
*/
ret = STMF_PS_ERROR;
goto out;
}
/*
* Reset the value resource as it is used below
*/
}
if (addRemoveFlag == ADD) {
veCnt++;
} else {
/* Check if this is the last one being removed */
if (veCnt == 1) {
/*
* Delete the pg and get out if this is the last
* view entry
*/
ret = STMF_PS_ERROR;
}
goto out;
} else {
veCnt--;
}
}
/*
* Set the view entry count
*/
/*
* Add the value to the transaction entry
*/
ret = STMF_PS_ERROR;
goto out;
}
/*
* Create a transaction entry resource for the view entry name
*/
if (entryVeName == NULL) {
ret = STMF_PS_ERROR;
goto out;
}
if (addRemoveFlag == ADD) {
/*
* If adding, create a property with the view entry name
*/
if (scf_error() == SCF_ERROR_EXISTS) {
} else {
"transaction property new %s/%s "
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
}
goto out;
}
} else {
/*
* If removing, delete the existing property with the view
* entry name
*/
viewEntryPgName) == -1) {
if (scf_error() == SCF_ERROR_NOT_FOUND) {
} else {
"transaction property delete %s/%s "
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
}
goto out;
}
}
/*
* Commit property transaction
*/
if (commitRet == 0) {
} else {
ret = STMF_PS_ERROR;
}
goto out;
}
out:
/*
* Free resources
*/
}
}
}
}
}
if (entryVeName != NULL) {
}
}
}
return (ret);
}
/*
* iPsAddViewEntry
*
* Add a view entry property group and optionally, a logical unit property
* group if it does not exist.
*
* luName - ascii hexadecimal logical unit identifier
* viewEntryName - name of view entry (VIEW_ENTRY_nn)
* viewEntry - pointer to stmfViewEntry structure
*/
static int
{
int i = 0;
int j = 0;
int ret;
int backoutRet;
int commitRet;
/*
* Init the service handle
*/
if (ret != STMF_PS_SUCCESS) {
goto out;
}
/*
* Allocate scf resources
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/*
* allocate value and entry resources for scf
*/
for (i = 0; i < VIEW_ENTRY_STRUCT_CNT; i++) {
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
}
i = 0;
/*
* Create the View Entry property group
*/
0, pg) == -1) {
if (scf_error() == SCF_ERROR_EXISTS) {
} else {
ret = STMF_PS_ERROR;
}
goto out;
}
/*
* Add the view entry as properties on the view entry group
*/
/*
* Begin property update transaction
*/
ret = STMF_PS_ERROR;
goto out;
}
/*
* Add allHosts property
*/
if (scf_error() == SCF_ERROR_EXISTS) {
} else {
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
}
goto out;
}
/* Set the allHosts value */
/*
* Add the allHosts value to the transaction
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
i++;
/*
* Create hostGroup property
*/
if (scf_error() == SCF_ERROR_EXISTS) {
} else {
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
}
goto out;
}
/*
* Set the value for hostGroup
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/*
* Add the hostGroup value to the transaction entry
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
i++;
/*
* Create the allTargets property
*/
if (scf_error() == SCF_ERROR_EXISTS) {
} else {
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
}
goto out;
}
/*
* Set the allTargets value
*/
/*
* Add the allTargets value to the transaction
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
i++;
/*
* Create targetGroup property
*/
if (scf_error() == SCF_ERROR_EXISTS) {
} else {
"failed - %s", viewEntryPgName,
ret = STMF_PS_ERROR;
}
goto out;
}
/*
* Set the value for targetGroup
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/*
* Add targetGroup value to the transaction
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
i++;
/*
* Create the luNbr property
*/
SCF_TYPE_OPAQUE) == -1) {
if (scf_error() == SCF_ERROR_EXISTS) {
} else {
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
}
goto out;
}
/*
* Set the luNbr
*/
ret = STMF_PS_ERROR;
goto out;
}
/*
* Add luNbr to the transaction entry
*/
ret = STMF_PS_ERROR;
goto out;
}
/*
* Now that we've successfully added the view entry,
* update the logical unit property group or create
* it if it does not exist
*/
/*
* If we did not add the view entry name to the logical unit,
* make sure we do not commit the transaction
*/
if (ret != STMF_PS_SUCCESS) {
goto out;
}
/*
* Commit property transaction
*/
if (commitRet == 0) {
} else {
ret = STMF_PS_ERROR;
}
}
if (ret != STMF_PS_SUCCESS) {
/*
* If we did not commit, try to remove the view entry name
* from the logical unit.
* If that fails, we're now inconsistent.
*/
REMOVE);
if (backoutRet != STMF_PS_SUCCESS) {
"possible inconsistency - %s", luPgName,
scf_strerror(scf_error()));
}
/*
* We are still in an error scenario even though the remove
* lu view entry succeeded.
*/
goto out;
}
out:
/*
* Free resources
*/
}
}
/* if there was an error, delete the created pg if one was created */
}
}
}
}
/*
* Free value and entry scf resources
*/
if (i > 0) {
for (j = 0; j < VIEW_ENTRY_STRUCT_CNT; j++) {
scf_value_destroy(value[j]);
scf_entry_destroy(entry[j]);
}
}
return (ret);
}
/*
* psClearProviderData
*
* providerName - name of provider data to clear
*/
int
{
goto out;
}
if (ret != STMF_PS_SUCCESS) {
goto out;
}
/*
* Allocate scf resources
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/*
* create the property group name
*/
/*
* delete provider property group
*/
if (scf_error() != SCF_ERROR_NOT_FOUND) {
ret = STMF_PS_ERROR;
goto out;
} else {
pgNotFound = B_TRUE;
}
}
ret = STMF_PS_ERROR;
goto out;
}
if (pgNotFound) {
}
out:
/*
* Free resources
*/
}
}
}
return (ret);
}
/*
* iPsCreateDeleteGroup
*
* Creates or deletes a group (target or host)
*
* When creating a group, two properties are created. One to hold the group
* name and the other to hold the group members.
*
* pgName - Property group name
* groupName - group name to create
* addRemoveFlag - ADD_GROUP/REMOVE_GROUP
*
* returns:
* STMF_PS_SUCCESS on success
* STMF_PS_ERROR_* on failure
*/
static int
{
int commitRet;
if (ret != STMF_PS_SUCCESS) {
goto out;
}
/*
* Allocate scf resources
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/*
* Get the property group being modified
*/
if (scf_error() == SCF_ERROR_NOT_FOUND &&
addRemoveFlag == ADD) {
ret = STMF_PS_ERROR;
}
} else if (scf_error() == SCF_ERROR_NOT_FOUND) {
} else {
ret = STMF_PS_ERROR;
}
if (ret != STMF_PS_SUCCESS) {
goto out;
}
}
/*
* propIter is the iterator handle
*/
ret = STMF_PS_ERROR;
goto out;
}
/*
* Iterate through the group names.
* If we find it in the list, it's an error when addRemoveFlag == ADD.
*/
ret = STMF_PS_ERROR;
break;
}
/*
* Skip over member list properties
*/
continue;
}
ret = STMF_PS_ERROR;
break;
}
sizeof (tmpbuf)) == -1) {
ret = STMF_PS_ERROR;
break;
}
if (addRemoveFlag == ADD) {
}
/*
* buf1 contains the name for REMOVE
*/
break;
}
}
if (ret != STMF_PS_SUCCESS) {
goto out;
}
goto out;
}
/*
* If we're adding, we need to create a new property name for the
* new group
*/
if (addRemoveFlag == ADD) {
"buffer overflow on property name %s",
buf1);
ret = STMF_PS_ERROR;
break;
}
if (scf_error() != SCF_ERROR_NOT_FOUND) {
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
}
break;
}
}
}
/*
* Now create the new member list property for the new group
*/
STMF_MEMBER_LIST_SUFFIX) > sizeof (buf2)) {
buf1);
ret = STMF_PS_ERROR;
goto out;
}
/*
* buf1 now contains the name of the property if it was found in the
* list in the case of delete or the next available property name
* in the case of create
*
* buf2 now contains the member list property name
*/
ret = STMF_PS_ERROR;
goto out;
}
if (addRemoveFlag == ADD) {
/*
* Create the property 'group name'
* This is the container for the group name
*/
SCF_TYPE_USTRING) == -1) {
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
ret = STMF_PS_ERROR;
goto out;
}
ret = STMF_PS_ERROR;
goto out;
}
/*
* Create the property 'group list'
* This is the container for the group members
*/
SCF_TYPE_USTRING) == -1) {
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
} else {
/*
* Delete the property 'group name'
*/
== -1) {
"transaction property delete %s/%s failed - %s",
ret = STMF_PS_ERROR;
goto out;
}
/*
* Delete the property 'group list'
*/
== -1) {
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
}
if (ret != STMF_PS_SUCCESS) {
goto out;
}
if (commitRet == 0) {
} else {
ret = STMF_PS_ERROR;
}
}
out:
/*
* Free resources
*/
}
}
}
}
}
}
}
}
}
return (ret);
}
/*
* iPsGetGroupList
*
* pgName - Property group name
* groupList - pointer to pointer to stmfGroupList structure. On success,
* contains the list of groups
*
* returns:
* STMF_PS_SUCCESS on success
* STMF_PS_ERROR_* on failure
*/
static int
{
int memberCnt = 0;
int i = 0;
if (ret != STMF_PS_SUCCESS) {
goto out;
}
/*
* Allocate scf resources
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
if (scf_error() == SCF_ERROR_NOT_FOUND) {
} else {
ret = STMF_PS_ERROR;
}
goto out;
}
/*
* propIter is the iterator handle
*/
ret = STMF_PS_ERROR;
goto out;
}
ret = STMF_PS_ERROR;
break;
}
/*
* Skip over member list properties
*/
continue;
}
memberCnt++;
}
/*
* propIter is the iterator handle
*/
ret = STMF_PS_ERROR;
goto out;
}
memberCnt * sizeof (stmfGroupName));
goto out;
}
/*
* In order to get a list of groups, simply get all of the
* properties that are not member list properties, i.e. the group
* name properties.
* It's possible for this list to grow beyond what was originally
* read so just ensure we're not writing beyond our allocated buffer
* by ensuring i < memberCnt
*/
(i < memberCnt)) {
ret = STMF_PS_ERROR;
break;
}
/*
* Skip over member list properties
*/
continue;
}
ret = STMF_PS_ERROR;
break;
}
ret = STMF_PS_ERROR;
break;
}
}
if (ret != STMF_PS_SUCCESS) {
goto out;
}
out:
/*
* Free resources
*/
}
}
}
}
}
}
return (ret);
}
/*
* iPsGetGroupMemberList
*
* pgName - Property group name
* groupName - group name (host group or target group)
* groupMemberList - pointer to pointer to stmfGroupProperties structure. On
* success, contains the list of group members
*
* returns:
* STMF_PS_SUCCESS on success
* STMF_PS_ERROR_* on failure
*/
static int
{
int i = 0;
int memberCnt;
int len;
/*
* init the service handle
*/
if (ret != STMF_PS_SUCCESS) {
goto out;
}
/*
* Allocate scf resources
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/*
* get the service property group handle
*/
if (scf_error() == SCF_ERROR_NOT_FOUND) {
} else {
ret = STMF_PS_ERROR;
}
goto out;
}
/*
* Get the property handle
* based on the target or host group name
*/
ret = STMF_PS_ERROR;
goto out;
}
/*
* valueIter is the iterator handle
*/
ret = STMF_PS_ERROR;
goto out;
}
ret = STMF_PS_ERROR;
break;
}
i++;
}
/*
* valueIter is the iterator handle
*/
ret = STMF_PS_ERROR;
goto out;
}
memberCnt = i;
if (*groupMemberList == NULL) {
goto out;
}
i = 0;
(i < memberCnt)) {
== -1) {
ret = STMF_PS_ERROR;
break;
}
(*groupMemberList)->cnt++;
} else {
ret = STMF_PS_ERROR;
break;
}
}
if (ret != STMF_PS_SUCCESS) {
goto out;
}
out:
/*
* Free resources
*/
}
}
}
}
if (valueLookup != NULL) {
}
}
return (ret);
}
int
{
int ret;
if (ret != STMF_PS_SUCCESS) {
return (STMF_PS_ERROR);
}
/*
* Free resources
*/
}
}
return (ret);
}
int
{
int ret;
if (ret != STMF_PS_SUCCESS) {
return (STMF_PS_ERROR);
}
/*
* Free resources
*/
}
}
return (ret);
}
static int
{
char *iPersistType;
int commitRet;
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/* set to default */
}
if (*persistType == STMF_PERSIST_SMF) {
} else if (*persistType == STMF_PERSIST_NONE) {
} else {
ret = STMF_PS_ERROR;
goto out;
}
}
/*
* get stmf data property group
*/
if (scf_error() == SCF_ERROR_NOT_FOUND) {
} else {
ret = STMF_PS_ERROR;
}
goto out;
}
/* find persistence property */
/*
* Get the persistence property
*/
if (scf_error() == SCF_ERROR_NOT_FOUND) {
} else {
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
}
/* no persist property found */
/*
* If we have no persistType property, go ahead
* and create it with the user specified value or
* the default value.
*/
/*
* Begin the transaction
*/
ret = STMF_PS_ERROR;
goto out;
}
if (ret) {
"%s/%s failed - %s", STMF_DATA_GROUP,
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
} else {
"%s/%s failed - %s", STMF_DATA_GROUP,
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
}
/*
* set the persist type
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/*
* add the value to the transaction
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
if (commitRet == 0) {
} else {
ret = STMF_PS_ERROR;
}
goto out;
}
/* reset return value */
/* get the persist property */
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/*
* Get the value of the persist property
*/
== -1) {
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
}
} else {
ret = STMF_PS_ERROR;
goto out;
}
}
out:
/*
* Free resources.
* handle and svc should not be free'd here. They're
* free'd elsewhere
*/
}
}
}
}
}
return (ret);
}
int
{
}
int
{
}
static int
{
char *psStmfPropVal;
char *psStmfProp;
int commitRet;
ret = STMF_PS_ERROR;
goto out;
}
/*
* Init the service handle
*/
if (ret != STMF_PS_SUCCESS) {
goto out;
}
/*
* Allocate scf resources
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
switch (propType) {
case STMF_DEFAULT_LU_STATE :
break;
break;
default :
ret = STMF_PS_ERROR;
goto out;
/* NOTREACHED */
break;
}
}
switch (propType) {
case STMF_DEFAULT_LU_STATE :
== 0) {
} else {
ret = STMF_PS_ERROR;
goto out;
}
break;
== 0) {
} else {
ret = STMF_PS_ERROR;
goto out;
}
break;
default :
ret = STMF_PS_ERROR;
goto out;
/* NOTREACHED */
break;
}
}
/*
* get stmf data property group
*/
if (scf_error() == SCF_ERROR_NOT_FOUND) {
} else {
ret = STMF_PS_ERROR;
}
goto out;
}
/*
* get the stmf props property, if exists
*/
if (scf_error() == SCF_ERROR_NOT_FOUND) {
} else {
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
}
/* if stmf prop is not found or while setting the prop */
/*
* Begin the transaction
*/
ret = STMF_PS_ERROR;
goto out;
}
if (ret) {
"%s/%s failed - %s", STMF_DATA_GROUP,
ret = STMF_PS_ERROR;
goto out;
}
} else {
"transaction property change "
"%s/%s failed - %s",
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
}
/*
* set stmf prop value
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/*
* add the value to the transaction
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
"failed - %s", STMF_DATA_GROUP,
scf_strerror(scf_error()));
if (commitRet == 0) {
} else {
ret = STMF_PS_ERROR;
}
goto out;
}
"%s/%s failed - %s",
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/* get stmfProp */
== -1) {
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
}
== 0) {
== 0) {
} else {
ret = STMF_PS_ERROR;
goto out;
}
}
out:
/*
* Free resources.
*/
}
}
}
}
}
}
}
return (ret);
}
/*
* Initialize scf stmf service access
* handle - returned handle
* service - returned service handle
*
* Both handle and service must be destroyed by the caller
*/
static int
{
int ret;
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto err;
}
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto err;
}
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto err;
}
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto err;
}
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto err;
}
scf_strerror(scf_error()));
goto err;
}
/*
* Get and check the version number
*/
if (ret != STMF_PS_SUCCESS) {
goto err;
}
if (version != STMF_SMF_VERSION) {
goto err;
}
/* we only need destroy the scope here */
return (STMF_PS_SUCCESS);
err:
}
}
}
return (ret);
}
/*
* called by iPsInit only
* iPsGetServiceVersion
*/
static int
{
int commitRet;
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/*
* get stmf data property group
*/
if (scf_error() == SCF_ERROR_NOT_FOUND) {
} else {
ret = STMF_PS_ERROR;
goto out;
}
}
/* create the group */
if (ret == STMF_PS_ERROR_NOT_FOUND) {
/*
* create the property group.
*/
ret = STMF_PS_ERROR;
goto out;
}
/* reset return value */
}
/* find version property */
/*
* Get the version property
*/
if (scf_error() == SCF_ERROR_NOT_FOUND) {
} else {
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
}
/* no version property found */
if (ret == STMF_PS_ERROR_NOT_FOUND) {
/*
* If we have no version property, go ahead
* and create it. We're obviously making an assumption
* here that someone did not delete the existing property
* and that this is the initial set and the initial call
* to iPsInit.
* If they did delete it, this will simply plant this
* library's version on this service. That may or may not be
* correct and we have no way of determining that.
*/
/*
* Begin the transaction
*/
ret = STMF_PS_ERROR;
goto out;
}
"transaction property new %s/%s failed - %s",
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/*
* set the version number
*/
/*
* add the value to the transaction
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
if (commitRet == 0) {
} else {
ret = STMF_PS_ERROR;
}
goto out;
}
/* reset return value */
} else {
/* get the version property */
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/*
* Get the actual value of the view entry count property
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
}
out:
/*
* Free resources.
* handle and svc should not be free'd here. They're
* free'd elsewhere
*/
}
}
}
}
}
return (ret);
}
/*
* iPsGetActualGroupName
*
* pgName - Property group name
* groupName - requested group name
* actualName - actual group name to reference (len must be >= MAXNAMELEN)
*
* returns:
* STMF_PS_SUCCESS on success
* STMF_PS_ERROR_* on failure
*/
static int
{
int ret;
if (ret != STMF_PS_SUCCESS) {
goto out;
}
/*
* Allocate scf resources
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/*
* get group list property group
*/
if (scf_error() == SCF_ERROR_NOT_FOUND) {
} else {
ret = STMF_PS_ERROR;
}
goto out;
}
/*
* propIter is the iterator handle
*/
ret = STMF_PS_ERROR;
goto out;
}
/*
* Iterate through group properties searching for the requested
* group name. When we find it, we need to get the property name
* since it refers to the actual group name.
*/
/* initialize to not found */
ret = STMF_PS_ERROR;
break;
}
/*
* Skip over non-member list properties
*/
continue;
}
ret = STMF_PS_ERROR;
break;
}
ret = STMF_PS_ERROR;
break;
}
/*
* When we find a match, set success and break
*/
break;
}
}
/*
* if we didn't find it, ret is set to STMF_PS_ERROR_GROUP_NOT_FOUND
*/
out:
/*
* Free resources
*/
}
}
}
}
}
}
return (ret);
}
/*
* psAddHostGroupMember
*
* Add a host group member to a host group,
*
* Input: groupName - name of group to which the member is added
* memberName - name of group member to add
*/
int
{
int ret;
if (ret != STMF_PS_SUCCESS) {
return (ret);
}
sizeof (groupPropListName)) {
return (STMF_PS_ERROR);
}
memberName, ADD));
}
/*
* psAddTargetGroupMember
*
* Add a target port group member to a target group
*
* Input: groupName - name of group to which the member is added
* memberName - name of group member to add. Must be nul terminated.
*/
int
{
int ret;
if (ret != STMF_PS_SUCCESS) {
return (ret);
}
sizeof (groupPropListName)) {
return (STMF_PS_ERROR);
}
memberName, ADD));
}
/*
* psAddViewEntry
*
* luGuid - logical unit identifier
* viewEntry - pointer to viewEntry allocated by the caller that contains
* the values to set for this view entry
*
* returns:
* STMF_PS_SUCCESS on success
* STMF_PS_ERROR_* on failure
*/
int
{
/* grab the signal hold lock */
(void) pthread_mutex_lock(&sigSetLock);
/*
* hold signals until we're done
*/
if (holdSignal(&sigmaskRestore) != 0) {
(void) pthread_mutex_unlock(&sigSetLock);
return (STMF_PS_ERROR);
}
if (ret != STMF_PS_SUCCESS) {
goto out;
}
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/* Convert to ASCII uppercase hexadecimal string */
"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
/*
* Format of view entry property group name:
* VE-<view_entry_name>-<lu_name>
*/
out:
/*
* Okay, we're done. Release the signals
*/
if (releaseSignal(&sigmaskRestore) != 0) {
/*
* Don't set this as an STMF_PS_ERROR_*. We succeeded
* the requested operation. But we do need to log it.
*/
}
/*
* Free resources
*/
}
}
}
/* release the signal hold lock */
(void) pthread_mutex_unlock(&sigSetLock);
return (ret);
}
/*
* psCheckService
*
* Purpose: Checks whether service exists
*
*/
int
{
int ret;
/*
* Free resources
*/
}
}
return (ret);
}
/*
* psCreateHostGroup
*
* groupName - name of group to create
*
* returns:
* STMF_PS_SUCCESS on success
* STMF_PS_ERROR_* on failure
*/
int
{
}
/*
* psCreateTargetGroup
*
* groupName - name of group to create
*
* returns:
* STMF_PS_SUCCESS on success
* STMF_PS_ERROR_* on failure
*/
int
{
}
/*
* psDeleteHostGroup
*
* groupName - name of group to delete
*
* returns:
* STMF_PS_SUCCESS on success
* STMF_PS_ERROR_* on failure
*/
int
{
}
/*
* psDeleteTargetGroup
*
* groupName - name of group to delete
*
* returns:
* STMF_PS_SUCCESS on success
* STMF_PS_ERROR_* on failure
*/
int
{
REMOVE));
}
/*
* psGetHostGroupList
*
* groupList - pointer to pointer to stmfGroupList. Contains the list
* of host groups on successful return.
*
* returns:
* STMF_PS_SUCCESS on success
* STMF_PS_ERROR_* on failure
*/
int
{
}
/*
* psGetLogicalUnitList
*
*
*/
int
{
int guidCnt = 0;
int i = 0, j;
if (ret != STMF_PS_SUCCESS) {
goto out;
}
/*
* Allocate scf resources
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/*
* pgIter is the iterator handle
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
break;
}
/*
* Only count LU property groups
*/
guidCnt++;
}
}
/*
* pgIter is the iterator handle
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
goto out;
}
/*
* the property groups. Just make sure we don't write beyond our
* allocated buffer by checking to ensure i < guidCnt.
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
break;
}
/*
* Only use LU property groups
*/
continue;
}
"%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
for (j = 0; j < sizeof (stmfGuid); j++) {
}
}
if (ret != STMF_PS_SUCCESS) {
goto out;
}
out:
/*
* Free resources
*/
}
}
}
}
return (ret);
}
/*
* psGetTargetGroupList
*
* groupList - pointer to pointer to stmfGroupList. Contains the list
* of target groups on successful return.
*
* returns:
* STMF_PS_SUCCESS on success
* STMF_PS_ERROR_* on failure
*/
int
{
}
/*
* psGetHostGroupMemberList
*
* groupName - group name for which to retrieve a member list
* groupMemberList - pointer to pointer to stmfGroupProperties list
*
* returns:
* STMF_PS_SUCCESS on success
* STMF_PS_ERROR_* on failure
*/
int
{
int ret;
if (ret != STMF_PS_SUCCESS) {
return (ret);
}
sizeof (groupPropListName)) {
return (STMF_PS_ERROR);
}
}
/*
* psGetTargetGroupMemberList
*
* groupName - group name for which to retrieve a member list
* groupMemberList - pointer to pointer to stmfGroupProperties list
*
* returns:
* STMF_PS_SUCCESS on success
* STMF_PS_ERROR_* on failure
*/
int
{
int ret;
if (ret != STMF_PS_SUCCESS) {
return (ret);
}
sizeof (groupPropListName)) {
return (STMF_PS_ERROR);
}
return (iPsGetGroupMemberList(STMF_TARGET_GROUPS,
}
/*
* qsort function
* sort on veIndex
*/
static int
{
return (1);
return (-1);
return (0);
}
/*
* psGetViewEntryList
*
* luGuid - identifier of logical unit for which to retrieve a view entry list
* viewEntryList - pointer to pointer to stmfViewEntryList. It will be allocated
* on successful return.
*
* returns:
* STMF_PS_SUCCESS on success
* STMF_PS_ERROR_* on failure
*/
int
{
uint64_t i = 0;
if (ret != STMF_PS_SUCCESS) {
goto out;
}
/*
* Allocate scf resources
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/* Convert to ASCII uppercase hexadecimal string */
"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
/* form the LU property group name (LU-<guid>) */
/* get the property group associated with this LU */
if (scf_error() == SCF_ERROR_NOT_FOUND) {
} else {
ret = STMF_PS_ERROR;
}
goto out;
}
/* get the view entry count property */
ret = STMF_PS_ERROR;
goto out;
}
ret = STMF_PS_ERROR;
goto out;
}
/*
* Get the actual value of the view entry count property
*/
ret = STMF_PS_ERROR;
goto out;
}
/*
* propIter is the iterator handle
*/
ret = STMF_PS_ERROR;
goto out;
}
/*
* alloc the list based on the view entry count
*/
if (*viewEntryList == NULL) {
goto out;
}
i = 0;
/*
* iterate through the view entry properties to find the
* view entries
*/
/* find match for view entry property */
sizeof (viewEntryPgName)) != -1) {
strlen(STMF_VE_PREFIX)) != 0) {
continue;
}
/*
* We've exceeded our alloc limit
* break with error
*/
if (i == veCnt) {
ret = STMF_PS_ERROR;
break;
}
break;
}
i++;
/* set the list count */
(*viewEntryList)->cnt++;
} else {
ret = STMF_PS_ERROR;
break;
}
}
if (ret != STMF_PS_SUCCESS) {
goto out;
}
/*
* We're sorting the final list here based on the veIndex
* If we don't, the caller is going to have to do it to reap
* some intelligent output.
*/
sizeof (stmfViewEntry), viewEntryCompare);
out:
/*
* Free resources
*/
}
}
}
}
}
}
return (ret);
}
/*
* iPsGetViewEntry
*
* viewEntryPgName - view entry property group name to retrieve
* viewEntry - pointer to stmfViewEntry structure allocated by the caller
*
* returns:
* STMF_PS_SUCCESS on success
* STMF_PS_ERROR_* on failure
*/
static int
{
char *indexPtr;
if (ret != STMF_PS_SUCCESS) {
goto out;
}
/*
* Allocate scf resources
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/*
* get the service property group view entry handle
*/
if (scf_error() == SCF_ERROR_NOT_FOUND) {
} else {
ret = STMF_PS_ERROR;
}
goto out;
}
/*
* get index
* format is: VE-<veIndex>-GUID
*/
if (!indexPtr) {
ret = STMF_PS_ERROR;
goto out;
}
/* Set the index */
/* get allHosts property */
prop) == -1) {
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/* set allHosts */
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/* get hostGroup property */
prop) == -1) {
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
sizeof (groupName)) == -1) {
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/* set hostGroup */
/* get allTargets property */
prop) == -1) {
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/* set allTargets */
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/* get targetGroup property */
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
sizeof (groupName)) == -1) {
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/* set targetGroup */
/* get luNbr property */
prop) == -1) {
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/* set luNbr */
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/* set luNbrValid to true since we just got it */
out:
/*
* Free resources
*/
}
}
}
}
}
return (ret);
}
/*
* psRemoveHostGroupMember
*
* Remove a host group member from a host group,
*
* groupName - name of group from which the member is removed
* memberName - name of group member to remove
*
* returns:
* STMF_PS_SUCCESS on success
* STMF_PS_ERROR_* on failure
*/
int
{
int ret;
if (ret != STMF_PS_SUCCESS) {
return (ret);
}
sizeof (groupPropListName)) {
return (STMF_PS_ERROR);
}
memberName, REMOVE));
}
/*
* psRemoveTargetGroupMember
*
* Remove a target port group member from an target port group,
*
* groupName - name of group from which the member is removed
* memberName - name of group member to remove
*
* returns:
* STMF_PS_SUCCESS on success
* STMF_PS_ERROR_* on failure
*/
int
{
int ret;
if (ret != STMF_PS_SUCCESS) {
return (ret);
}
sizeof (groupPropListName)) {
return (STMF_PS_ERROR);
}
memberName, REMOVE));
}
/*
* psGetProviderData
*
* Retrieves an nvlist on a per provider basis
*
* providerName - property group name to use
* nvl - nvlist to retrieve
*
*/
int
{
int i;
goto out;
}
if (ret != STMF_PS_SUCCESS) {
goto out;
}
/*
* create the property group name
*/
/*
* Allocate scf resources
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/*
* Retrieve the existing property group.
*/
if (scf_error() != SCF_ERROR_NOT_FOUND) {
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
} else {
goto out;
}
}
/*
* Get the STMF_PROVIDER_DATA_PROP_COUNT property
*/
prop) == -1) {
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/*
* Get the STMF_PROVIDER_DATA_PROP_COUNT value
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/*
* Now get the actual value from the value handle
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/* Has the caller requested the token to be set? */
if (setToken) {
/*
* Get the STMF_PROVIDER_DATA_PROP_SET_COUNT property
* If it doesn't exist, we assume it to be zero.
*/
*setToken = 0;
prop) == -1) {
if (scf_error() == SCF_ERROR_NOT_FOUND) {
} else {
"failed - %s", pgName,
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
}
if (foundSetCnt) {
/*
* Get the STMF_PROVIDER_DATA_PROP_SET_COUNT value
*/
"get property value %s/%s failed - %s",
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/*
* Now get the actual value from the value handle
* and set the caller's token
*/
"get integer value %s/%s failed - %s",
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
}
}
if (nvlistEncoded == NULL) {
goto out;
}
for (i = 0; i < blockCnt; i++) {
/*
* create the name to use for the property
*/
"%s-%d", STMF_PROVIDER_DATA_PROP_PREFIX, i);
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/*
* Set the data block offset
*/
if (actualBlockSize == -1) {
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
}
ret = STMF_PS_ERROR;
goto out;
}
out:
/*
* Free resources
*/
}
}
}
}
}
if (nvlistEncoded != NULL) {
}
return (ret);
}
/*
* psGetProviderDataList
*
* Retrieves the list of providers that currently store persistent data
*
* providerList - pointer to a pointer to an stmfProviderList structure
* On success, this will contain the list of providers
* currently storing persistent data.
*/
int
{
int providerCnt = 0;
int i = 0, j;
if (ret != STMF_PS_SUCCESS) {
goto out;
}
*providerList = NULL;
/*
* Allocate scf resources
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/*
* pgIter is the iterator handle
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
break;
}
/*
* Only count LU property groups
*/
strlen(STMF_PROVIDER_DATA_PREFIX)) == 0) {
providerCnt++;
}
}
/*
* pgIter is the iterator handle
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
if (*providerList == NULL) {
goto out;
}
/*
* the property groups. Just make sure we don't write beyond our
* allocated buffer by checking to ensure i < providerCnt.
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
break;
}
/*
* Only use provider data property groups
*/
strlen(STMF_PROVIDER_DATA_PREFIX)) != 0) {
continue;
}
/*
* Get the STMF_PROVIDER_DATA_PROP_TYPE property
*/
prop) == -1) {
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
break;
}
/*
* Get the STMF_PROVIDER_DATA_PROP_TYPE value
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
break;
}
/*
* Now get the actual value from the value handle
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
break;
}
/* determine offset for copy of provider name */
/* copy provider name to caller's list */
i++;
(*providerList)->cnt++;
}
if (ret != STMF_PS_SUCCESS) {
free(*providerList);
goto out;
}
out:
/*
* Free resources
*/
}
}
}
}
}
}
return (ret);
}
/*
* psSetProviderData
*
* Stores a packed nvlist on a per provider basis
*
* providerName - property group name to use
* nvl - nvlist to store
* providerType - type of provider (logical unit or port)
*
*/
int
{
/* represents arrays of entry and value pointers for scf */
/*
* operations
*/
int i, j = 0;
int blockOffset;
int commitRet;
goto out;
}
if (ret != STMF_PS_SUCCESS) {
goto out;
}
/*
* create the property group name
*/
/*
* Allocate scf resources
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/*
* Get the existing property group
*/
if (scf_error() != SCF_ERROR_NOT_FOUND) {
ret = STMF_PS_ERROR;
goto out;
} else {
/*
* create the property group.
*/
ret = STMF_PS_ERROR;
goto out;
}
}
}
/*
* Begin the transaction
*/
ret = STMF_PS_ERROR;
goto out;
}
if (!newPg) {
/*
* Get the STMF_PROVIDER_DATA_PROP_COUNT property
*/
prop) == -1) {
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/*
* Get the STMF_PROVIDER_DATA_PROP_COUNT value
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/*
* Now get the actual value from the value handle
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
}
/*
* Get the STMF_PROVIDER_DATA_PROP_SET_COUNT property
* If it doesn't exist, we'll create it later after successfully
* setting the data.
*/
prop) == -1) {
if (scf_error() == SCF_ERROR_NOT_FOUND) {
} else {
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
}
if (foundSetCnt) {
/*
* Get the STMF_PROVIDER_DATA_PROP_SET_COUNT value
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/*
* Now get the actual value from the value handle
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/*
* Compare the setCnt prop to the caller's.
*/
goto out;
}
}
setCnt++;
/*
* prepare the list for writing
*/
NV_ENCODE_XDR, 0) != 0) {
pgName);
goto out;
}
/* Determine how many chunks we need to write */
blockCnt++;
/* allocate entry and value resources for writing those chunks */
* blockCnt);
goto out;
}
* blockCnt);
goto out;
}
/*
* allocate entry delete resources for deleting anything existing
* that is more than the new block count. We could leave them around
* without suffering any ill effects but it will be cleaner to look at
* in smf tools if they are deleted.
*/
if (oldBlockCnt > blockCnt) {
if (deleteEntry == NULL) {
pgName);
goto out;
}
}
for (i = 0; i < blockCnt; i++) {
/*
* Create the entry resource for the prop
*/
ret = STMF_PS_ERROR;
goto out;
}
/* bump alloc count for addEntry allocation */
/*
* create the name to use for the property
*/
"%s-%d", STMF_PROVIDER_DATA_PROP_PREFIX, i);
/*
* Create the new property
*/
if (scf_error() == SCF_ERROR_EXISTS) {
addEntry[i], dataPropertyName,
SCF_TYPE_OPAQUE) == -1) {
"change %s/%s failed - %s",
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
} else {
"transaction property new %s/%s "
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
}
/*
* Create the value resource for the prop
*/
ret = STMF_PS_ERROR;
goto out;
}
/* bump alloc count for addValue allocation */
/*
* Set the data block offset and size
*/
if ((STMF_PROVIDER_DATA_PROP_SIZE * (i + 1))
> nvlistEncodedSize) {
- STMF_PROVIDER_DATA_PROP_SIZE * i;
} else {
}
if (scf_value_set_opaque(addValue[i],
ret = STMF_PS_ERROR;
goto out;
}
/*
* Add the data block to the transaction entry
*/
ret = STMF_PS_ERROR;
goto out;
}
}
/*
* Now we need to delete any chunks (properties) that are no longer
* needed. Iterate through the rest of the chunks deleting each.
*/
for (i = blockCnt; i < oldBlockCnt; i++) {
/*
* Create the entry resource for the prop
*/
if (deleteEntry[j] == NULL) {
ret = STMF_PS_ERROR;
goto out;
}
/*
* create the name to use for the property
*/
"%s-%d", STMF_PROVIDER_DATA_PROP_PREFIX, i);
/*
* Delete the existing property
*/
dataPropertyName) == -1) {
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
}
if (newPg) {
/*
* Ensure the read_authorization property is set
* for the group
*/
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
pgName, "read_authorization",
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
pgName, "read_authorization",
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
}
/* create or change the count property */
if (scf_error() == SCF_ERROR_EXISTS) {
SCF_TYPE_COUNT) == -1) {
"%s/%s failed - %s", pgName,
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
} else {
"failed - %s", pgName,
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
}
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/* create or change the set count property */
if (scf_error() == SCF_ERROR_EXISTS) {
SCF_TYPE_COUNT) == -1) {
"transaction property change %s/%s "
"failed - %s", pgName,
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
} else {
"failed - %s", pgName,
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
}
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/* create or change the provider type property */
if (scf_error() == SCF_ERROR_EXISTS) {
SCF_TYPE_INTEGER) == -1) {
"transaction property change %s/%s "
"failed - %s", pgName,
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
} else {
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
}
switch (providerType) {
case STMF_PORT_PROVIDER_TYPE:
case STMF_LU_PROVIDER_TYPE:
break;
default:
ret = STMF_PS_ERROR;
goto out;
}
ret = STMF_PS_ERROR;
goto out;
}
if (commitRet == 0) {
} else {
ret = STMF_PS_ERROR;
}
goto out;
}
/* pass the new token back to the caller if requested */
}
out:
/*
* Free resources
*/
}
}
}
}
}
for (i = 0; i < addEntryAlloc; i++) {
}
for (i = 0; i < addValueAlloc; i++) {
}
for (i = 0; i < deleteEntryAlloc; i++) {
}
}
}
}
}
}
}
}
}
}
if (nvlistEncoded != NULL) {
}
return (ret);
}
/*
* psGetViewEntry
*
* Purpose: Get a single view entry based on the logical unit identifier and
* view entry index
*
* lu - logical unit identifier
* viewEntryIndex - index of view entry
* ve - caller allocated stmfViewEntry structure. On success, this will
* contain the retrieved view entry
*/
int
{
if (ret != STMF_PS_SUCCESS) {
goto out;
}
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/* Convert to ASCII uppercase hexadecimal string */
"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
/*
* Format of view entry property group name:
* VE-<view_entry_index>-<lu_name>
*/
if (scf_error() == SCF_ERROR_NOT_FOUND) {
} else {
ret = STMF_PS_ERROR;
}
goto out;
}
ret = STMF_PS_ERROR;
goto out;
}
out:
/*
* Free resources
*/
}
}
}
return (ret);
}
/*
* psRemoveViewEntry
*
* Remove a view entry
*
* luGuid - identifier of logical unit from which to remove view entry
* viewEntryIndex - view entry name to remove
*
* returns:
* STMF_PS_SUCCESS on success
* STMF_PS_ERROR_* on failure
*/
int
{
/* grab the signal hold lock */
(void) pthread_mutex_lock(&sigSetLock);
/*
* hold signals until we're done
*/
if (holdSignal(&sigmaskRestore) != 0) {
(void) pthread_mutex_unlock(&sigSetLock);
return (STMF_PS_ERROR);
}
if (ret != STMF_PS_SUCCESS) {
goto out;
}
scf_strerror(scf_error()));
ret = STMF_PS_ERROR;
goto out;
}
/* Convert to ASCII uppercase hexadecimal string */
"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
/*
* Format of view entry property group name:
* VE-<view_entry_index>-<lu_name>
*/
if (scf_error() == SCF_ERROR_NOT_FOUND) {
} else {
ret = STMF_PS_ERROR;
}
goto out;
}
/*
* update the logical unit property group to remove
* the view entry and update the view entry count
* If it fails, we won't delete the property group so that
* we maintain consistency.
*/
REMOVE)) != STMF_PS_SUCCESS) {
goto out;
}
/*
* Delete the view entry. If this fails, we should try to add
* the logical unit view entry property group back otherwise
* we're inconsistent.
*/
scf_strerror(scf_error()));
ADD)) != STMF_PS_SUCCESS) {
"inconsistency - %s", viewEntryPgName,
scf_strerror(scf_error()));
}
ret = STMF_PS_ERROR;
goto out;
}
out:
/*
* Okay, we're done. Release the signals
*/
if (releaseSignal(&sigmaskRestore) != 0) {
/*
* Don't set this as an STMF_PS_ERROR_*. We succeeded
* the requested operation. But we do need to log it.
*/
}
/*
* Free resources
*/
}
}
}
/* release the signal hold lock */
(void) pthread_mutex_unlock(&sigSetLock);
return (ret);
}
/*
* holdSignal
*
* Hold SIGINT, SIGTERM, SIGQUIT until further notice.
*
* Saves old signal mask on a per thread basis
* and saves action for the process.
*
* Installs action for above signals.
*
* locks held: sigSetLock
*
* returns:
* 0 on success
* non-zero otherwise
*/
static int
{
/*
* Return existing signal mask for this thread
*/
return (1);
}
/*
* Have we set the actions for the signals we want to catch?
*/
if (!actionSet) {
return (1);
}
return (1);
}
return (1);
}
}
/*
* We still need to change the mask for the current thread
*/
if (sigfillset(&sigmask) != 0) {
return (1);
}
return (1);
}
return (0);
}
/*
* releaseSignal
*
* Re-install the original signal mask and signal actions
*
* Also, raise any signals that were caught during the hold period and clear
* the signal from the caught set (signalsCaught).
*
* locks held: sigSetLock
*
* Returns
* 0 on success
* non-zero otherwise
*/
static int
{
int ret = 0;
ret = 1;
}
ret = 1;
}
ret = 1;
}
/*
* Restore previous signal mask for this thread
*/
}
/*
* Now raise signals that were raised while we were held
*/
}
}
}
return (ret);
}