#include <stdlib.h>
#include <stdio.h>
#include <wchar.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <libintl.h>
#include <errno.h>
#include <string.h>
#include <assert.h>
#include <libnvpair.h>
#include <pthread.h>
#include <syslog.h>
#include <libstmf.h>
#include <netinet/in.h>
#include <inttypes.h>
#include <store.h>
#include <locale.h>
#include <math.h>
#include <libstmf_impl.h>
#include <sys/stmf_ioctl.h>
#include <sys/stmf_sbd_ioctl.h>
#include <sys/pppt_ioctl.h>
#include <macros.h>
#define STMF_PATH "/devices/pseudo/stmf@0:admin"
#define SBD_PATH "/devices/pseudo/stmf_sbd@0:admin"
#define PPPT_PATH "/devices/pseudo/pppt@0:pppt"
#define EUI "eui."
#define WWN "wwn."
#define IQN "iqn."
#define LU_ASCII_GUID_SIZE 32
#define LU_GUID_SIZE 16
#define OUI_ASCII_SIZE 6
#define HOST_ID_ASCII_SIZE 8
#define OUI_SIZE 3
#define HOST_ID_SIZE 4
#define IDENT_LENGTH_BYTE 3
#define ALLOC_LU 8192
#define ALLOC_TARGET_PORT 2048
#define ALLOC_PROVIDER 64
#define ALLOC_GROUP 2048
#define ALLOC_SESSION 2048
#define ALLOC_VE 256
#define ALLOC_PP_DATA_SIZE 128*1024
#define ALLOC_GRP_MEMBER 256
#define MAX_ISCSI_NAME 223
#define MAX_SERIAL_SIZE 252 + 1
#define MAX_LU_ALIAS_SIZE 256
#define MAX_SBD_PROPS MAXPATHLEN + MAX_SERIAL_SIZE + MAX_LU_ALIAS_SIZE
#define OPEN_STMF 0
#define OPEN_EXCL_STMF O_EXCL
#define OPEN_SBD 0
#define OPEN_EXCL_SBD O_EXCL
#define OPEN_PPPT 0
#define OPEN_EXCL_PPPT O_EXCL
#define LOGICAL_UNIT_TYPE 0
#define TARGET_TYPE 1
#define STMF_SERVICE_TYPE 2
#define HOST_GROUP 1
#define TARGET_GROUP 2
#define STMF_DEFAULT_PERSIST STMF_PERSIST_SMF
#define MAX_PROVIDER_RETRY 30
static int openStmf(int, int *fd);
static int openSbd(int, int *fd);
static int openPppt(int, int *fd);
static int groupIoctl(int fd, int cmd, stmfGroupName *);
static int loadStore(int fd);
static int initializeConfig();
static int groupMemberIoctl(int fd, int cmd, stmfGroupName *, stmfDevid *);
static int guidCompare(const void *, const void *);
static int addViewEntryIoctl(int fd, stmfGuid *, stmfViewEntry *);
static int loadHostGroups(int fd, stmfGroupList *);
static int loadTargetGroups(int fd, stmfGroupList *);
static int getStmfState(stmf_state_desc_t *);
static int setStmfState(int fd, stmf_state_desc_t *, int);
static int setProviderData(int fd, char *, nvlist_t *, int, uint64_t *);
static int createDiskResource(luResourceImpl *);
static int createDiskLu(diskResource *, stmfGuid *);
static int deleteDiskLu(stmfGuid *luGuid);
static int getDiskProp(luResourceImpl *, uint32_t, char *, size_t *);
static int getDiskAllProps(stmfGuid *luGuid, luResource *hdl);
static int loadDiskPropsFromDriver(luResourceImpl *, sbd_lu_props_t *);
static int removeGuidFromDiskStore(stmfGuid *);
static int addGuidToDiskStore(stmfGuid *, char *);
static int persistDiskGuid(stmfGuid *, char *, boolean_t);
static int setDiskProp(luResourceImpl *, uint32_t, const char *);
static int getDiskGlobalProp(uint32_t prop, char *propVal, size_t *propLen);
static int checkHexUpper(char *);
static int strToShift(const char *);
static int niceStrToNum(const char *, uint64_t *);
static void diskError(uint32_t, int *);
static int importDiskLu(char *fname, stmfGuid *);
static int modifyDiskLu(diskResource *, stmfGuid *, const char *);
static int modifyDiskLuProp(stmfGuid *, const char *, uint32_t, const char *);
static int validateModifyDiskProp(uint32_t);
static uint8_t iGetPersistMethod();
static int groupListIoctl(stmfGroupList **, int);
static int iLoadGroupFromPs(stmfGroupList **, int);
static int groupMemberListIoctl(stmfGroupName *, stmfGroupProperties **, int);
static int getProviderData(char *, nvlist_t **, int, uint64_t *);
static int setDiskStandby(stmfGuid *luGuid);
static int setDiskGlobalProp(uint32_t, const char *);
static int viewEntryCompare(const void *, const void *);
static void deleteNonActiveLus();
static int loadStmfProp(int fd);
static pthread_mutex_t persistenceTypeLock = PTHREAD_MUTEX_INITIALIZER;
static int iPersistType = 0;
static boolean_t iLibSetPersist = B_FALSE;
static int
openStmf(int flag, int *fd)
{
int ret = STMF_STATUS_ERROR;
if ((*fd = open(STMF_PATH, O_NDELAY | O_RDONLY | flag)) != -1) {
ret = STMF_STATUS_SUCCESS;
} else {
if (errno == EBUSY) {
ret = STMF_ERROR_BUSY;
} else if (errno == EACCES) {
ret = STMF_ERROR_PERM;
} else {
ret = STMF_STATUS_ERROR;
}
syslog(LOG_DEBUG, "openStmf:open failure:%s:errno(%d)",
STMF_PATH, errno);
}
return (ret);
}
static int
openSbd(int flag, int *fd)
{
int ret = STMF_STATUS_ERROR;
if ((*fd = open(SBD_PATH, O_NDELAY | O_RDONLY | flag)) != -1) {
ret = STMF_STATUS_SUCCESS;
} else {
if (errno == EBUSY) {
ret = STMF_ERROR_BUSY;
} else if (errno == EACCES) {
ret = STMF_ERROR_PERM;
} else {
ret = STMF_STATUS_ERROR;
}
syslog(LOG_DEBUG, "openSbd:open failure:%s:errno(%d)",
SBD_PATH, errno);
}
return (ret);
}
static int
openPppt(int flag, int *fd)
{
int ret = STMF_STATUS_ERROR;
if ((*fd = open(PPPT_PATH, O_RDONLY | flag)) != -1) {
ret = STMF_STATUS_SUCCESS;
} else {
if (errno == EBUSY) {
ret = STMF_ERROR_BUSY;
} else if (errno == EACCES) {
ret = STMF_ERROR_PERM;
} else {
ret = STMF_STATUS_ERROR;
}
syslog(LOG_DEBUG, "openPppt:open failure:%s:errno(%d)",
PPPT_PATH, errno);
}
return (ret);
}
static int
initializeConfig()
{
int ret;
stmfState state;
ret = stmfGetState(&state);
if (ret != STMF_STATUS_SUCCESS) {
return (ret);
}
if (state.configState == STMF_CONFIG_STATE_INIT_DONE ||
state.configState == STMF_CONFIG_STATE_INIT) {
return (STMF_STATUS_SUCCESS);
}
ret = stmfLoadConfig();
if (ret != STMF_STATUS_SUCCESS) {
syslog(LOG_DEBUG,
"initializeConfig:stmfLoadConfig:error(%d)", ret);
return (ret);
}
ret = stmfGetState(&state);
if (ret != STMF_STATUS_SUCCESS) {
syslog(LOG_DEBUG,
"initializeConfig:stmfGetState:error(%d)", ret);
return (ret);
}
if (state.configState != STMF_CONFIG_STATE_INIT_DONE) {
syslog(LOG_DEBUG, "initializeConfig:state.configState(%d)",
state.configState);
ret = STMF_STATUS_ERROR;
}
return (ret);
}
static int
groupIoctl(int fd, int cmd, stmfGroupName *groupName)
{
int ret = STMF_STATUS_SUCCESS;
int ioctlRet;
stmf_iocdata_t stmfIoctl;
stmf_group_name_t iGroupName;
bzero(&iGroupName, sizeof (iGroupName));
bcopy(groupName, &iGroupName.name, strlen((char *)groupName));
iGroupName.name_size = strlen((char *)groupName);
bzero(&stmfIoctl, sizeof (stmfIoctl));
stmfIoctl.stmf_version = STMF_VERSION_1;
stmfIoctl.stmf_ibuf_size = sizeof (iGroupName);
stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&iGroupName;
ioctlRet = ioctl(fd, cmd, &stmfIoctl);
if (ioctlRet != 0) {
switch (errno) {
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
default:
switch (stmfIoctl.stmf_error) {
case STMF_IOCERR_TG_EXISTS:
case STMF_IOCERR_HG_EXISTS:
ret = STMF_ERROR_EXISTS;
break;
case STMF_IOCERR_TG_IN_USE:
case STMF_IOCERR_HG_IN_USE:
ret = STMF_ERROR_GROUP_IN_USE;
break;
case STMF_IOCERR_INVALID_HG:
case STMF_IOCERR_INVALID_TG:
ret = STMF_ERROR_NOT_FOUND;
break;
default:
syslog(LOG_DEBUG,
"groupIoctl:error(%d)",
stmfIoctl.stmf_error);
ret = STMF_STATUS_ERROR;
break;
}
break;
}
}
return (ret);
}
static int
groupMemberIoctl(int fd, int cmd, stmfGroupName *groupName, stmfDevid *devid)
{
int ret = STMF_STATUS_SUCCESS;
int ioctlRet;
stmf_iocdata_t stmfIoctl;
stmf_group_op_data_t stmfGroupData;
bzero(&stmfGroupData, sizeof (stmfGroupData));
bcopy(groupName, &stmfGroupData.group.name, strlen((char *)groupName));
stmfGroupData.group.name_size = strlen((char *)groupName);
stmfGroupData.ident[IDENT_LENGTH_BYTE] = devid->identLength;
bcopy(&(devid->ident), &stmfGroupData.ident[IDENT_LENGTH_BYTE + 1],
devid->identLength);
bzero(&stmfIoctl, sizeof (stmfIoctl));
stmfIoctl.stmf_version = STMF_VERSION_1;
stmfIoctl.stmf_ibuf_size = sizeof (stmfGroupData);
stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&stmfGroupData;
ioctlRet = ioctl(fd, cmd, &stmfIoctl);
if (ioctlRet != 0) {
switch (errno) {
case EBUSY:
switch (stmfIoctl.stmf_error) {
case STMF_IOCERR_TG_NEED_TG_OFFLINE:
ret = STMF_ERROR_TG_ONLINE;
break;
default:
ret = STMF_ERROR_BUSY;
break;
}
break;
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
default:
switch (stmfIoctl.stmf_error) {
case STMF_IOCERR_TG_ENTRY_EXISTS:
case STMF_IOCERR_HG_ENTRY_EXISTS:
ret = STMF_ERROR_EXISTS;
break;
case STMF_IOCERR_INVALID_TG_ENTRY:
case STMF_IOCERR_INVALID_HG_ENTRY:
ret =
STMF_ERROR_MEMBER_NOT_FOUND;
break;
case STMF_IOCERR_INVALID_TG:
case STMF_IOCERR_INVALID_HG:
ret =
STMF_ERROR_GROUP_NOT_FOUND;
break;
default:
syslog(LOG_DEBUG,
"groupMemberIoctl:error"
"(%d)",
stmfIoctl.stmf_error);
ret = STMF_STATUS_ERROR;
break;
}
break;
}
}
return (ret);
}
static int
viewEntryCompare(const void *p1, const void *p2)
{
stmfViewEntry *v1 = (stmfViewEntry *)p1, *v2 = (stmfViewEntry *)p2;
if (v1->veIndex > v2->veIndex)
return (1);
if (v1->veIndex < v2->veIndex)
return (-1);
return (0);
}
static int
guidCompare(const void *p1, const void *p2)
{
stmfGuid *g1 = (stmfGuid *)p1, *g2 = (stmfGuid *)p2;
int i;
for (i = 0; i < sizeof (stmfGuid); i++) {
if (g1->guid[i] > g2->guid[i])
return (1);
if (g1->guid[i] < g2->guid[i])
return (-1);
}
return (0);
}
int
stmfAddToHostGroup(stmfGroupName *hostGroupName, stmfDevid *hostName)
{
int ret;
int fd;
if (hostGroupName == NULL ||
(strnlen((char *)hostGroupName, sizeof (stmfGroupName))
== sizeof (stmfGroupName)) || hostName == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
ret = initializeConfig();
if (ret != STMF_STATUS_SUCCESS) {
return (ret);
}
if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_HG_ENTRY, hostGroupName,
hostName)) != STMF_STATUS_SUCCESS) {
goto done;
}
if (iGetPersistMethod() == STMF_PERSIST_NONE) {
goto done;
}
ret = psAddHostGroupMember((char *)hostGroupName,
(char *)hostName->ident);
switch (ret) {
case STMF_PS_SUCCESS:
ret = STMF_STATUS_SUCCESS;
break;
case STMF_PS_ERROR_EXISTS:
ret = STMF_ERROR_EXISTS;
break;
case STMF_PS_ERROR_GROUP_NOT_FOUND:
ret = STMF_ERROR_GROUP_NOT_FOUND;
break;
case STMF_PS_ERROR_BUSY:
ret = STMF_ERROR_BUSY;
break;
case STMF_PS_ERROR_SERVICE_NOT_FOUND:
ret = STMF_ERROR_SERVICE_NOT_FOUND;
break;
case STMF_PS_ERROR_VERSION_MISMATCH:
ret = STMF_ERROR_SERVICE_DATA_VERSION;
break;
default:
syslog(LOG_DEBUG,
"stmfAddToHostGroup:psAddHostGroupMember:error(%d)",
ret);
ret = STMF_STATUS_ERROR;
break;
}
done:
(void) close(fd);
return (ret);
}
int
stmfAddToTargetGroup(stmfGroupName *targetGroupName, stmfDevid *targetName)
{
int ret;
int fd;
if (targetGroupName == NULL ||
(strnlen((char *)targetGroupName, sizeof (stmfGroupName))
== sizeof (stmfGroupName)) || targetName == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
ret = initializeConfig();
if (ret != STMF_STATUS_SUCCESS) {
return (ret);
}
if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_TG_ENTRY,
targetGroupName, targetName)) != STMF_STATUS_SUCCESS) {
goto done;
}
if (iGetPersistMethod() == STMF_PERSIST_NONE) {
goto done;
}
ret = psAddTargetGroupMember((char *)targetGroupName,
(char *)targetName->ident);
switch (ret) {
case STMF_PS_SUCCESS:
ret = STMF_STATUS_SUCCESS;
break;
case STMF_PS_ERROR_EXISTS:
ret = STMF_ERROR_EXISTS;
break;
case STMF_PS_ERROR_GROUP_NOT_FOUND:
ret = STMF_ERROR_GROUP_NOT_FOUND;
break;
case STMF_PS_ERROR_BUSY:
ret = STMF_ERROR_BUSY;
break;
case STMF_PS_ERROR_SERVICE_NOT_FOUND:
ret = STMF_ERROR_SERVICE_NOT_FOUND;
break;
case STMF_PS_ERROR_VERSION_MISMATCH:
ret = STMF_ERROR_SERVICE_DATA_VERSION;
break;
default:
syslog(LOG_DEBUG,
"stmfAddToTargetGroup:psAddTargetGroupMember:"
"error(%d)", ret);
ret = STMF_STATUS_ERROR;
break;
}
done:
(void) close(fd);
return (ret);
}
static int
addViewEntryIoctl(int fd, stmfGuid *lu, stmfViewEntry *viewEntry)
{
int ret = STMF_STATUS_SUCCESS;
int ioctlRet;
stmf_iocdata_t stmfIoctl;
stmf_view_op_entry_t ioctlViewEntry;
bzero(&ioctlViewEntry, sizeof (ioctlViewEntry));
ioctlViewEntry.ve_lu_number_valid = viewEntry->luNbrValid;
ioctlViewEntry.ve_all_hosts = viewEntry->allHosts;
ioctlViewEntry.ve_all_targets = viewEntry->allTargets;
if (viewEntry->allHosts == B_FALSE) {
bcopy(viewEntry->hostGroup, &ioctlViewEntry.ve_host_group.name,
sizeof (stmfGroupName));
ioctlViewEntry.ve_host_group.name_size =
strlen((char *)viewEntry->hostGroup);
}
if (viewEntry->allTargets == B_FALSE) {
bcopy(viewEntry->targetGroup,
&ioctlViewEntry.ve_target_group.name,
sizeof (stmfGroupName));
ioctlViewEntry.ve_target_group.name_size =
strlen((char *)viewEntry->targetGroup);
}
if (viewEntry->luNbrValid) {
bcopy(viewEntry->luNbr, &ioctlViewEntry.ve_lu_nbr,
sizeof (ioctlViewEntry.ve_lu_nbr));
}
bcopy(lu, &ioctlViewEntry.ve_guid, sizeof (stmfGuid));
bzero(&stmfIoctl, sizeof (stmfIoctl));
stmfIoctl.stmf_version = STMF_VERSION_1;
stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry);
stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry;
stmfIoctl.stmf_obuf_size = sizeof (ioctlViewEntry);
stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&ioctlViewEntry;
ioctlRet = ioctl(fd, STMF_IOCTL_ADD_VIEW_ENTRY, &stmfIoctl);
if (ioctlRet != 0) {
switch (errno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
ret = STMF_ERROR_PERM;
break;
case EACCES:
switch (stmfIoctl.stmf_error) {
case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
ret = STMF_ERROR_CONFIG_NONE;
break;
default:
ret = STMF_ERROR_PERM;
break;
}
break;
default:
switch (stmfIoctl.stmf_error) {
case STMF_IOCERR_LU_NUMBER_IN_USE:
ret = STMF_ERROR_LUN_IN_USE;
break;
case STMF_IOCERR_VIEW_ENTRY_CONFLICT:
ret = STMF_ERROR_VE_CONFLICT;
break;
case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
ret = STMF_ERROR_CONFIG_NONE;
break;
case STMF_IOCERR_INVALID_HG:
ret = STMF_ERROR_INVALID_HG;
break;
case STMF_IOCERR_INVALID_TG:
ret = STMF_ERROR_INVALID_TG;
break;
default:
syslog(LOG_DEBUG,
"addViewEntryIoctl"
":error(%d)",
stmfIoctl.stmf_error);
ret = STMF_STATUS_ERROR;
break;
}
break;
}
goto done;
}
viewEntry->veIndex = ioctlViewEntry.ve_ndx;
if (ioctlViewEntry.ve_lu_number_valid) {
bcopy(&ioctlViewEntry.ve_lu_nbr, viewEntry->luNbr,
sizeof (ioctlViewEntry.ve_lu_nbr));
}
viewEntry->luNbrValid = B_TRUE;
done:
return (ret);
}
int
stmfAddViewEntry(stmfGuid *lu, stmfViewEntry *viewEntry)
{
int ret;
int fd;
stmfViewEntry iViewEntry;
if (lu == NULL || viewEntry == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
bzero(&iViewEntry, sizeof (iViewEntry));
if (!viewEntry->allHosts) {
bcopy(viewEntry->hostGroup, iViewEntry.hostGroup,
sizeof (iViewEntry.hostGroup));
} else {
iViewEntry.allHosts = B_TRUE;
}
if (!viewEntry->allTargets) {
bcopy(viewEntry->targetGroup, iViewEntry.targetGroup,
sizeof (iViewEntry.targetGroup));
} else {
iViewEntry.allTargets = B_TRUE;
}
if (viewEntry->luNbrValid) {
iViewEntry.luNbrValid = B_TRUE;
bcopy(viewEntry->luNbr, iViewEntry.luNbr,
sizeof (iViewEntry.luNbr));
}
viewEntry->veIndexValid = B_FALSE;
if (psCheckService() != STMF_STATUS_SUCCESS) {
return (STMF_ERROR_SERVICE_NOT_FOUND);
}
ret = initializeConfig();
if (ret != STMF_STATUS_SUCCESS) {
return (ret);
}
if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
ret = addViewEntryIoctl(fd, lu, &iViewEntry);
if (ret != STMF_STATUS_SUCCESS) {
goto done;
}
if (iGetPersistMethod() == STMF_PERSIST_NONE) {
goto done;
}
ret = psAddViewEntry(lu, &iViewEntry);
switch (ret) {
case STMF_PS_SUCCESS:
ret = STMF_STATUS_SUCCESS;
break;
case STMF_PS_ERROR_NOT_FOUND:
ret = STMF_ERROR_NOT_FOUND;
break;
case STMF_PS_ERROR_BUSY:
ret = STMF_ERROR_BUSY;
break;
case STMF_PS_ERROR_SERVICE_NOT_FOUND:
ret = STMF_ERROR_SERVICE_NOT_FOUND;
break;
case STMF_PS_ERROR_VERSION_MISMATCH:
ret = STMF_ERROR_SERVICE_DATA_VERSION;
break;
default:
syslog(LOG_DEBUG,
"stmfAddViewEntry:psAddViewEntry:error(%d)", ret);
ret = STMF_STATUS_ERROR;
break;
}
done:
(void) close(fd);
if (ret == STMF_STATUS_SUCCESS) {
viewEntry->veIndexValid = iViewEntry.veIndexValid;
viewEntry->veIndex = iViewEntry.veIndex;
viewEntry->luNbrValid = B_TRUE;
bcopy(iViewEntry.luNbr, viewEntry->luNbr,
sizeof (iViewEntry.luNbr));
}
return (ret);
}
int
stmfClearProviderData(char *providerName, int providerType)
{
int ret;
int fd;
int ioctlRet;
int savedErrno;
stmf_iocdata_t stmfIoctl;
stmf_ppioctl_data_t ppi;
ret = initializeConfig();
if (ret != STMF_STATUS_SUCCESS) {
return (ret);
}
if (providerName == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
if (providerType != STMF_LU_PROVIDER_TYPE &&
providerType != STMF_PORT_PROVIDER_TYPE) {
return (STMF_ERROR_INVALID_ARG);
}
if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
bzero(&ppi, sizeof (ppi));
(void) strncpy(ppi.ppi_name, providerName, sizeof (ppi.ppi_name));
switch (providerType) {
case STMF_LU_PROVIDER_TYPE:
ppi.ppi_lu_provider = 1;
break;
case STMF_PORT_PROVIDER_TYPE:
ppi.ppi_port_provider = 1;
break;
default:
ret = STMF_ERROR_INVALID_ARG;
goto done;
}
bzero(&stmfIoctl, sizeof (stmfIoctl));
stmfIoctl.stmf_version = STMF_VERSION_1;
stmfIoctl.stmf_ibuf_size = sizeof (stmf_ppioctl_data_t);
stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ppi;
ioctlRet = ioctl(fd, STMF_IOCTL_CLEAR_PP_DATA, &stmfIoctl);
if (ioctlRet != 0) {
savedErrno = errno;
switch (savedErrno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
default:
syslog(LOG_DEBUG,
"stmfClearProviderData:ioctl error(%d)",
ioctlRet);
ret = STMF_STATUS_ERROR;
break;
}
if (savedErrno != ENOENT) {
goto done;
}
}
if (iGetPersistMethod() == STMF_PERSIST_NONE) {
goto done;
}
ret = psClearProviderData(providerName, providerType);
switch (ret) {
case STMF_PS_SUCCESS:
ret = STMF_STATUS_SUCCESS;
break;
case STMF_PS_ERROR_NOT_FOUND:
ret = STMF_ERROR_NOT_FOUND;
break;
case STMF_PS_ERROR_BUSY:
ret = STMF_ERROR_BUSY;
break;
case STMF_PS_ERROR_SERVICE_NOT_FOUND:
ret = STMF_ERROR_SERVICE_NOT_FOUND;
break;
case STMF_PS_ERROR_VERSION_MISMATCH:
ret = STMF_ERROR_SERVICE_DATA_VERSION;
break;
default:
syslog(LOG_DEBUG,
"stmfClearProviderData:psClearProviderData"
":error(%d)", ret);
ret = STMF_STATUS_ERROR;
break;
}
done:
(void) close(fd);
return (ret);
}
int
stmfCreateHostGroup(stmfGroupName *hostGroupName)
{
int ret;
int fd;
if (hostGroupName == NULL ||
(strnlen((char *)hostGroupName, sizeof (stmfGroupName))
== sizeof (stmfGroupName))) {
return (STMF_ERROR_INVALID_ARG);
}
if (psCheckService() != STMF_STATUS_SUCCESS) {
return (STMF_ERROR_SERVICE_NOT_FOUND);
}
ret = initializeConfig();
if (ret != STMF_STATUS_SUCCESS) {
return (ret);
}
if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_HOST_GROUP,
hostGroupName)) != STMF_STATUS_SUCCESS) {
goto done;
}
if (iGetPersistMethod() == STMF_PERSIST_NONE) {
goto done;
}
ret = psCreateHostGroup((char *)hostGroupName);
switch (ret) {
case STMF_PS_SUCCESS:
ret = STMF_STATUS_SUCCESS;
break;
case STMF_PS_ERROR_EXISTS:
ret = STMF_ERROR_EXISTS;
break;
case STMF_PS_ERROR_BUSY:
ret = STMF_ERROR_BUSY;
break;
case STMF_PS_ERROR_SERVICE_NOT_FOUND:
ret = STMF_ERROR_SERVICE_NOT_FOUND;
break;
case STMF_PS_ERROR_VERSION_MISMATCH:
ret = STMF_ERROR_SERVICE_DATA_VERSION;
break;
default:
syslog(LOG_DEBUG,
"stmfCreateHostGroup:psCreateHostGroup:error(%d)",
ret);
ret = STMF_STATUS_ERROR;
break;
}
done:
(void) close(fd);
return (ret);
}
int
stmfCreateLu(luResource hdl, stmfGuid *luGuid)
{
int ret = STMF_STATUS_SUCCESS;
luResourceImpl *luPropsHdl = hdl;
if (hdl == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
if (luPropsHdl->type == STMF_DISK) {
ret = createDiskLu((diskResource *)luPropsHdl->resource,
luGuid);
} else {
return (STMF_ERROR_INVALID_ARG);
}
return (ret);
}
int
stmfCreateLuResource(uint16_t dType, luResource *hdl)
{
int ret = STMF_STATUS_SUCCESS;
if (dType != STMF_DISK || hdl == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
*hdl = calloc(1, sizeof (luResourceImpl));
if (*hdl == NULL) {
return (STMF_ERROR_NOMEM);
}
ret = createDiskResource((luResourceImpl *)*hdl);
if (ret != STMF_STATUS_SUCCESS) {
free(*hdl);
return (ret);
}
return (STMF_STATUS_SUCCESS);
}
static int
createDiskLu(diskResource *disk, stmfGuid *createdGuid)
{
int ret = STMF_STATUS_SUCCESS;
int dataFileNameLen = 0;
int metaFileNameLen = 0;
int serialNumLen = 0;
int luAliasLen = 0;
int luMgmtUrlLen = 0;
int sluBufSize = 0;
int bufOffset = 0;
int fd = 0;
int ioctlRet;
int savedErrno;
stmfGuid guid;
stmf_iocdata_t sbdIoctl = {0};
sbd_create_and_reg_lu_t *sbdLu = NULL;
if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
if (disk->luDataFileNameValid) {
dataFileNameLen = strlen(disk->luDataFileName);
} else {
(void) close(fd);
return (STMF_ERROR_MISSING_PROP_VAL);
}
sluBufSize += dataFileNameLen + 1;
if (disk->luMetaFileNameValid) {
metaFileNameLen = strlen(disk->luMetaFileName);
sluBufSize += metaFileNameLen + 1;
}
serialNumLen = strlen(disk->serialNum);
sluBufSize += serialNumLen;
if (disk->luAliasValid) {
luAliasLen = strlen(disk->luAlias);
sluBufSize += luAliasLen + 1;
}
if (disk->luMgmtUrlValid) {
luMgmtUrlLen = strlen(disk->luMgmtUrl);
sluBufSize += luMgmtUrlLen + 1;
}
sbdLu = (sbd_create_and_reg_lu_t *)calloc(1,
sizeof (sbd_create_and_reg_lu_t) + sluBufSize - 8);
if (sbdLu == NULL) {
return (STMF_ERROR_NOMEM);
}
sbdLu->slu_struct_size = sizeof (sbd_create_and_reg_lu_t) +
sluBufSize - 8;
if (metaFileNameLen) {
sbdLu->slu_meta_fname_valid = 1;
sbdLu->slu_meta_fname_off = bufOffset;
bcopy(disk->luMetaFileName, &(sbdLu->slu_buf[bufOffset]),
metaFileNameLen + 1);
bufOffset += metaFileNameLen + 1;
}
bcopy(disk->luDataFileName, &(sbdLu->slu_buf[bufOffset]),
dataFileNameLen + 1);
sbdLu->slu_data_fname_off = bufOffset;
bufOffset += dataFileNameLen + 1;
if (disk->serialNumValid) {
sbdLu->slu_serial_valid = 1;
sbdLu->slu_serial_off = bufOffset;
sbdLu->slu_serial_size = serialNumLen;
bcopy(disk->serialNum, &(sbdLu->slu_buf[bufOffset]),
serialNumLen);
bufOffset += serialNumLen;
}
if (disk->luAliasValid) {
sbdLu->slu_alias_valid = 1;
sbdLu->slu_alias_off = bufOffset;
bcopy(disk->luAlias, &(sbdLu->slu_buf[bufOffset]),
luAliasLen + 1);
bufOffset += luAliasLen + 1;
}
if (disk->luMgmtUrlValid) {
sbdLu->slu_mgmt_url_valid = 1;
sbdLu->slu_mgmt_url_off = bufOffset;
bcopy(disk->luMgmtUrl, &(sbdLu->slu_buf[bufOffset]),
luMgmtUrlLen + 1);
bufOffset += luMgmtUrlLen + 1;
}
if (disk->luSizeValid) {
sbdLu->slu_lu_size_valid = 1;
sbdLu->slu_lu_size = disk->luSize;
}
if (disk->luGuidValid) {
sbdLu->slu_guid_valid = 1;
bcopy(disk->luGuid, sbdLu->slu_guid, sizeof (disk->luGuid));
}
if (disk->vidValid) {
sbdLu->slu_vid_valid = 1;
bcopy(disk->vid, sbdLu->slu_vid, sizeof (disk->vid));
}
if (disk->pidValid) {
sbdLu->slu_pid_valid = 1;
bcopy(disk->pid, sbdLu->slu_pid, sizeof (disk->pid));
}
if (disk->revValid) {
sbdLu->slu_rev_valid = 1;
bcopy(disk->rev, sbdLu->slu_rev, sizeof (disk->rev));
}
if (disk->companyIdValid) {
sbdLu->slu_company_id_valid = 1;
sbdLu->slu_company_id = disk->companyId;
}
if (disk->hostIdValid) {
sbdLu->slu_host_id_valid = 1;
sbdLu->slu_host_id = disk->hostId;
}
if (disk->blkSizeValid) {
sbdLu->slu_blksize_valid = 1;
sbdLu->slu_blksize = disk->blkSize;
}
if (disk->writeProtectEnableValid) {
if (disk->writeProtectEnable) {
sbdLu->slu_write_protected = 1;
}
}
if (disk->writebackCacheDisableValid) {
sbdLu->slu_writeback_cache_disable_valid = 1;
if (disk->writebackCacheDisable) {
sbdLu->slu_writeback_cache_disable = 1;
}
}
sbdIoctl.stmf_version = STMF_VERSION_1;
sbdIoctl.stmf_ibuf_size = sbdLu->slu_struct_size;
sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdLu;
sbdIoctl.stmf_obuf_size = sbdLu->slu_struct_size;
sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdLu;
ioctlRet = ioctl(fd, SBD_IOCTL_CREATE_AND_REGISTER_LU, &sbdIoctl);
if (ioctlRet != 0) {
savedErrno = errno;
switch (savedErrno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
default:
diskError(sbdIoctl.stmf_error, &ret);
if (ret == STMF_STATUS_ERROR) {
syslog(LOG_DEBUG,
"createDiskLu:ioctl "
"error(%d) (%d) (%d)", ioctlRet,
sbdIoctl.stmf_error, savedErrno);
}
break;
}
}
if (ret != STMF_STATUS_SUCCESS) {
goto done;
}
if (createdGuid) {
bcopy(sbdLu->slu_guid, createdGuid->guid,
sizeof (sbdLu->slu_guid));
}
bcopy(sbdLu->slu_guid, guid.guid, sizeof (sbdLu->slu_guid));
if (disk->luMetaFileNameValid) {
ret = addGuidToDiskStore(&guid, disk->luMetaFileName);
} else {
ret = addGuidToDiskStore(&guid, disk->luDataFileName);
}
done:
free(sbdLu);
(void) close(fd);
return (ret);
}
int
stmfImportLu(uint16_t dType, char *fname, stmfGuid *luGuid)
{
int ret = STMF_STATUS_SUCCESS;
if (dType == STMF_DISK) {
ret = importDiskLu(fname, luGuid);
} else {
return (STMF_ERROR_INVALID_ARG);
}
return (ret);
}
static int
importDiskLu(char *fname, stmfGuid *createdGuid)
{
int ret = STMF_STATUS_SUCCESS;
int fd = 0;
int ioctlRet;
int savedErrno;
int metaFileNameLen;
stmfGuid iGuid;
int iluBufSize = 0;
sbd_import_lu_t *sbdLu = NULL;
stmf_iocdata_t sbdIoctl = {0};
if (fname == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
metaFileNameLen = strlen(fname);
iluBufSize += metaFileNameLen + 1;
sbdLu = (sbd_import_lu_t *)calloc(1,
sizeof (sbd_import_lu_t) + iluBufSize - 8);
if (sbdLu == NULL) {
(void) close(fd);
return (STMF_ERROR_NOMEM);
}
(void) strncpy(sbdLu->ilu_meta_fname, fname, metaFileNameLen);
sbdLu->ilu_struct_size = sizeof (sbd_import_lu_t) + iluBufSize - 8;
sbdIoctl.stmf_version = STMF_VERSION_1;
sbdIoctl.stmf_ibuf_size = sbdLu->ilu_struct_size;
sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdLu;
sbdIoctl.stmf_obuf_size = sbdLu->ilu_struct_size;
sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdLu;
ioctlRet = ioctl(fd, SBD_IOCTL_IMPORT_LU, &sbdIoctl);
if (ioctlRet != 0) {
if (createdGuid && sbdIoctl.stmf_error ==
SBD_RET_FILE_ALREADY_REGISTERED) {
bcopy(sbdLu->ilu_ret_guid, createdGuid->guid,
sizeof (sbdLu->ilu_ret_guid));
}
savedErrno = errno;
switch (savedErrno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
default:
diskError(sbdIoctl.stmf_error, &ret);
if (ret == STMF_STATUS_ERROR) {
syslog(LOG_DEBUG,
"importDiskLu:ioctl "
"error(%d) (%d) (%d)", ioctlRet,
sbdIoctl.stmf_error, savedErrno);
}
break;
}
}
if (ret != STMF_STATUS_SUCCESS) {
goto done;
}
if (createdGuid) {
bcopy(sbdLu->ilu_ret_guid, createdGuid->guid,
sizeof (sbdLu->ilu_ret_guid));
ret = addGuidToDiskStore(createdGuid, fname);
} else {
bcopy(sbdLu->ilu_ret_guid, iGuid.guid,
sizeof (sbdLu->ilu_ret_guid));
ret = addGuidToDiskStore(&iGuid, fname);
}
done:
free(sbdLu);
(void) close(fd);
return (ret);
}
static void
diskError(uint32_t stmfError, int *ret)
{
switch (stmfError) {
case SBD_RET_META_CREATION_FAILED:
case SBD_RET_ZFS_META_CREATE_FAILED:
*ret = STMF_ERROR_META_CREATION;
break;
case SBD_RET_INVALID_BLKSIZE:
*ret = STMF_ERROR_INVALID_BLKSIZE;
break;
case SBD_RET_FILE_ALREADY_REGISTERED:
*ret = STMF_ERROR_FILE_IN_USE;
break;
case SBD_RET_GUID_ALREADY_REGISTERED:
*ret = STMF_ERROR_GUID_IN_USE;
break;
case SBD_RET_META_PATH_NOT_ABSOLUTE:
case SBD_RET_META_FILE_LOOKUP_FAILED:
case SBD_RET_META_FILE_OPEN_FAILED:
case SBD_RET_META_FILE_GETATTR_FAILED:
case SBD_RET_NO_META:
*ret = STMF_ERROR_META_FILE_NAME;
break;
case SBD_RET_DATA_PATH_NOT_ABSOLUTE:
case SBD_RET_DATA_FILE_LOOKUP_FAILED:
case SBD_RET_DATA_FILE_OPEN_FAILED:
case SBD_RET_DATA_FILE_GETATTR_FAILED:
*ret = STMF_ERROR_DATA_FILE_NAME;
break;
case SBD_RET_FILE_SIZE_ERROR:
*ret = STMF_ERROR_FILE_SIZE_INVALID;
break;
case SBD_RET_SIZE_OUT_OF_RANGE:
*ret = STMF_ERROR_SIZE_OUT_OF_RANGE;
break;
case SBD_RET_LU_BUSY:
*ret = STMF_ERROR_LU_BUSY;
break;
case SBD_RET_WRITE_CACHE_SET_FAILED:
*ret = STMF_ERROR_WRITE_CACHE_SET;
break;
case SBD_RET_ACCESS_STATE_FAILED:
*ret = STMF_ERROR_ACCESS_STATE_SET;
break;
default:
*ret = STMF_STATUS_ERROR;
break;
}
}
static int
createDiskResource(luResourceImpl *hdl)
{
hdl->type = STMF_DISK;
hdl->resource = calloc(1, sizeof (diskResource));
if (hdl->resource == NULL) {
return (STMF_ERROR_NOMEM);
}
return (STMF_STATUS_SUCCESS);
}
int
stmfDeleteLu(stmfGuid *luGuid)
{
int ret = STMF_STATUS_SUCCESS;
stmfLogicalUnitProperties luProps;
if (luGuid == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps))
!= STMF_STATUS_SUCCESS) {
return (ret);
} else {
if (strcmp(luProps.providerName, "sbd") == 0) {
ret = deleteDiskLu(luGuid);
} else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) {
return (STMF_ERROR_NOT_FOUND);
} else {
return (STMF_ERROR_INVALID_ARG);
}
}
return (ret);
}
static int
deleteDiskLu(stmfGuid *luGuid)
{
int ret = STMF_STATUS_SUCCESS;
int fd;
int savedErrno;
int ioctlRet;
sbd_delete_lu_t deleteLu = {0};
stmf_iocdata_t sbdIoctl = {0};
if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
ret = removeGuidFromDiskStore(luGuid);
if (ret != STMF_STATUS_SUCCESS) {
goto done;
}
bcopy(luGuid, deleteLu.dlu_guid, sizeof (deleteLu.dlu_guid));
deleteLu.dlu_by_guid = 1;
sbdIoctl.stmf_version = STMF_VERSION_1;
sbdIoctl.stmf_ibuf_size = sizeof (deleteLu);
sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)&deleteLu;
ioctlRet = ioctl(fd, SBD_IOCTL_DELETE_LU, &sbdIoctl);
if (ioctlRet != 0) {
savedErrno = errno;
switch (savedErrno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
case ENOENT:
ret = STMF_ERROR_NOT_FOUND;
break;
default:
syslog(LOG_DEBUG,
"deleteDiskLu:ioctl error(%d) (%d) (%d)",
ioctlRet, sbdIoctl.stmf_error, savedErrno);
ret = STMF_STATUS_ERROR;
break;
}
}
done:
(void) close(fd);
return (ret);
}
int
stmfLuStandby(stmfGuid *luGuid)
{
int ret = STMF_STATUS_SUCCESS;
stmfLogicalUnitProperties luProps;
if (luGuid == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps))
!= STMF_STATUS_SUCCESS) {
return (ret);
} else {
if (strcmp(luProps.providerName, "sbd") == 0) {
ret = setDiskStandby(luGuid);
} else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) {
return (STMF_ERROR_NOT_FOUND);
} else {
return (STMF_ERROR_INVALID_ARG);
}
}
return (ret);
}
static int
setDiskStandby(stmfGuid *luGuid)
{
int ret = STMF_STATUS_SUCCESS;
stmf_iocdata_t sbdIoctl = {0};
sbd_set_lu_standby_t sbdLu = {0};
int ioctlRet;
int savedErrno;
int fd = 0;
if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
bcopy(luGuid, &sbdLu.stlu_guid, sizeof (stmfGuid));
sbdIoctl.stmf_version = STMF_VERSION_1;
sbdIoctl.stmf_ibuf_size = sizeof (sbd_set_lu_standby_t);
sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)&sbdLu;
ioctlRet = ioctl(fd, SBD_IOCTL_SET_LU_STANDBY, &sbdIoctl);
if (ioctlRet != 0) {
savedErrno = errno;
switch (savedErrno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
default:
diskError(sbdIoctl.stmf_error, &ret);
if (ret == STMF_STATUS_ERROR) {
syslog(LOG_DEBUG,
"setDiskStandby:ioctl "
"error(%d) (%d) (%d)", ioctlRet,
sbdIoctl.stmf_error, savedErrno);
}
break;
}
}
(void) close(fd);
return (ret);
}
int
stmfModifyLu(stmfGuid *luGuid, uint32_t prop, const char *propVal)
{
int ret = STMF_STATUS_SUCCESS;
stmfLogicalUnitProperties luProps;
if (luGuid == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps))
!= STMF_STATUS_SUCCESS) {
return (ret);
} else {
if (strcmp(luProps.providerName, "sbd") == 0) {
ret = modifyDiskLuProp(luGuid, NULL, prop, propVal);
} else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) {
return (STMF_ERROR_NOT_FOUND);
} else {
return (STMF_ERROR_INVALID_ARG);
}
}
return (ret);
}
int
stmfModifyLuByFname(uint16_t dType, const char *fname, uint32_t prop,
const char *propVal)
{
int ret = STMF_STATUS_SUCCESS;
if (fname == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
if (dType == STMF_DISK) {
ret = modifyDiskLuProp(NULL, fname, prop, propVal);
} else {
return (STMF_ERROR_INVALID_ARG);
}
return (ret);
}
static int
modifyDiskLuProp(stmfGuid *luGuid, const char *fname, uint32_t prop,
const char *propVal)
{
int ret = STMF_STATUS_SUCCESS;
luResource hdl = NULL;
luResourceImpl *luPropsHdl;
ret = stmfCreateLuResource(STMF_DISK, &hdl);
if (ret != STMF_STATUS_SUCCESS) {
return (ret);
}
ret = validateModifyDiskProp(prop);
if (ret != STMF_STATUS_SUCCESS) {
(void) stmfFreeLuResource(hdl);
return (STMF_ERROR_INVALID_PROP);
}
ret = stmfSetLuProp(hdl, prop, propVal);
if (ret != STMF_STATUS_SUCCESS) {
(void) stmfFreeLuResource(hdl);
return (ret);
}
luPropsHdl = hdl;
ret = modifyDiskLu((diskResource *)luPropsHdl->resource, luGuid, fname);
(void) stmfFreeLuResource(hdl);
return (ret);
}
static int
validateModifyDiskProp(uint32_t prop)
{
switch (prop) {
case STMF_LU_PROP_ALIAS:
case STMF_LU_PROP_SIZE:
case STMF_LU_PROP_MGMT_URL:
case STMF_LU_PROP_WRITE_PROTECT:
case STMF_LU_PROP_WRITE_CACHE_DISABLE:
return (STMF_STATUS_SUCCESS);
default:
return (STMF_STATUS_ERROR);
}
}
static int
modifyDiskLu(diskResource *disk, stmfGuid *luGuid, const char *fname)
{
int ret = STMF_STATUS_SUCCESS;
int luAliasLen = 0;
int luMgmtUrlLen = 0;
int mluBufSize = 0;
int bufOffset = 0;
int fd = 0;
int ioctlRet;
int savedErrno;
int fnameSize = 0;
stmf_iocdata_t sbdIoctl = {0};
sbd_modify_lu_t *sbdLu = NULL;
if (luGuid == NULL && fname == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
if (fname) {
fnameSize = strlen(fname) + 1;
mluBufSize += fnameSize;
}
if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
if (disk->luAliasValid) {
luAliasLen = strlen(disk->luAlias);
mluBufSize += luAliasLen + 1;
}
if (disk->luMgmtUrlValid) {
luMgmtUrlLen = strlen(disk->luMgmtUrl);
mluBufSize += luMgmtUrlLen + 1;
}
sbdLu = (sbd_modify_lu_t *)calloc(1,
sizeof (sbd_modify_lu_t) + mluBufSize - 8 + fnameSize);
if (sbdLu == NULL) {
(void) close(fd);
return (STMF_ERROR_NOMEM);
}
sbdLu->mlu_struct_size = sizeof (sbd_modify_lu_t) +
mluBufSize - 8 + fnameSize;
if (disk->luAliasValid) {
sbdLu->mlu_alias_valid = 1;
sbdLu->mlu_alias_off = bufOffset;
bcopy(disk->luAlias, &(sbdLu->mlu_buf[bufOffset]),
luAliasLen + 1);
bufOffset += luAliasLen + 1;
}
if (disk->luMgmtUrlValid) {
sbdLu->mlu_mgmt_url_valid = 1;
sbdLu->mlu_mgmt_url_off = bufOffset;
bcopy(disk->luMgmtUrl, &(sbdLu->mlu_buf[bufOffset]),
luMgmtUrlLen + 1);
bufOffset += luMgmtUrlLen + 1;
}
if (disk->luSizeValid) {
sbdLu->mlu_lu_size_valid = 1;
sbdLu->mlu_lu_size = disk->luSize;
}
if (disk->writeProtectEnableValid) {
sbdLu->mlu_write_protected_valid = 1;
if (disk->writeProtectEnable) {
sbdLu->mlu_write_protected = 1;
}
}
if (disk->writebackCacheDisableValid) {
sbdLu->mlu_writeback_cache_disable_valid = 1;
if (disk->writebackCacheDisable) {
sbdLu->mlu_writeback_cache_disable = 1;
}
}
if (luGuid) {
bcopy(luGuid, sbdLu->mlu_input_guid, sizeof (stmfGuid));
sbdLu->mlu_by_guid = 1;
} else {
sbdLu->mlu_fname_off = bufOffset;
bcopy(fname, &(sbdLu->mlu_buf[bufOffset]), fnameSize + 1);
sbdLu->mlu_by_fname = 1;
}
sbdIoctl.stmf_version = STMF_VERSION_1;
sbdIoctl.stmf_ibuf_size = sbdLu->mlu_struct_size;
sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdLu;
ioctlRet = ioctl(fd, SBD_IOCTL_MODIFY_LU, &sbdIoctl);
if (ioctlRet != 0) {
savedErrno = errno;
switch (savedErrno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
default:
diskError(sbdIoctl.stmf_error, &ret);
if (ret == STMF_STATUS_ERROR) {
syslog(LOG_DEBUG,
"modifyDiskLu:ioctl "
"error(%d) (%d) (%d)", ioctlRet,
sbdIoctl.stmf_error, savedErrno);
}
break;
}
}
if (ret != STMF_STATUS_SUCCESS) {
goto done;
}
done:
free(sbdLu);
(void) close(fd);
return (ret);
}
static int
removeGuidFromDiskStore(stmfGuid *guid)
{
return (persistDiskGuid(guid, NULL, B_FALSE));
}
static int
addGuidToDiskStore(stmfGuid *guid, char *filename)
{
return (persistDiskGuid(guid, filename, B_TRUE));
}
static int
persistDiskGuid(stmfGuid *guid, char *filename, boolean_t persist)
{
char guidAsciiBuf[LU_ASCII_GUID_SIZE + 1] = {0};
nvlist_t *nvl = NULL;
uint64_t setToken;
boolean_t retryGetProviderData = B_FALSE;
boolean_t newData = B_FALSE;
int ret = STMF_STATUS_SUCCESS;
int retryCnt = 0;
int stmfRet;
if (persist && !filename) {
return (1);
}
(void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf),
"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
"%02x%02x%02x%02x%02x%02x",
guid->guid[0], guid->guid[1], guid->guid[2], guid->guid[3],
guid->guid[4], guid->guid[5], guid->guid[6], guid->guid[7],
guid->guid[8], guid->guid[9], guid->guid[10], guid->guid[11],
guid->guid[12], guid->guid[13], guid->guid[14], guid->guid[15]);
do {
retryGetProviderData = B_FALSE;
stmfRet = stmfGetProviderDataProt("sbd", &nvl,
STMF_LU_PROVIDER_TYPE, &setToken);
if (stmfRet != STMF_STATUS_SUCCESS) {
if (persist && stmfRet == STMF_ERROR_NOT_FOUND) {
ret = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0);
if (ret != 0) {
syslog(LOG_DEBUG,
"unpersistGuid:nvlist_alloc(%d)",
ret);
ret = STMF_STATUS_ERROR;
goto done;
}
newData = B_TRUE;
} else {
if (persist) {
ret = stmfRet;
}
goto done;
}
}
if (persist) {
ret = nvlist_add_string(nvl, guidAsciiBuf, filename);
} else {
ret = nvlist_remove(nvl, guidAsciiBuf,
DATA_TYPE_STRING);
if (ret == ENOENT) {
ret = 0;
}
}
if (ret == 0) {
if (newData) {
stmfRet = stmfSetProviderDataProt("sbd", nvl,
STMF_LU_PROVIDER_TYPE, NULL);
} else {
stmfRet = stmfSetProviderDataProt("sbd", nvl,
STMF_LU_PROVIDER_TYPE, &setToken);
}
if (stmfRet != STMF_STATUS_SUCCESS) {
if (stmfRet == STMF_ERROR_BUSY) {
retryGetProviderData = B_TRUE;
if (retryCnt++ > MAX_PROVIDER_RETRY) {
ret = stmfRet;
break;
}
continue;
} else if (stmfRet ==
STMF_ERROR_PROV_DATA_STALE) {
nvlist_free(nvl);
nvl = NULL;
retryGetProviderData = B_TRUE;
if (retryCnt++ > MAX_PROVIDER_RETRY) {
ret = stmfRet;
break;
}
continue;
} else {
syslog(LOG_DEBUG,
"unpersistGuid:error(%x)", stmfRet);
ret = stmfRet;
}
break;
}
} else {
syslog(LOG_DEBUG,
"unpersistGuid:error nvlist_add/remove(%d)",
ret);
ret = STMF_STATUS_ERROR;
}
} while (retryGetProviderData);
done:
nvlist_free(nvl);
return (ret);
}
int
stmfGetLuProp(luResource hdl, uint32_t prop, char *propVal, size_t *propLen)
{
int ret = STMF_STATUS_SUCCESS;
luResourceImpl *luPropsHdl = hdl;
if (hdl == NULL || propLen == NULL || propVal == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
if (luPropsHdl->type == STMF_DISK) {
ret = getDiskProp(luPropsHdl, prop, propVal, propLen);
} else {
return (STMF_ERROR_INVALID_ARG);
}
return (ret);
}
int
stmfGetLuResource(stmfGuid *luGuid, luResource *hdl)
{
int ret = STMF_STATUS_SUCCESS;
stmfLogicalUnitProperties luProps;
if (hdl == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps))
!= STMF_STATUS_SUCCESS) {
return (ret);
} else {
if (strcmp(luProps.providerName, "sbd") == 0) {
ret = getDiskAllProps(luGuid, hdl);
} else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) {
return (STMF_ERROR_NOT_FOUND);
} else {
return (STMF_ERROR_INVALID_ARG);
}
}
return (ret);
}
static int
getDiskAllProps(stmfGuid *luGuid, luResource *hdl)
{
int ret = STMF_STATUS_SUCCESS;
int fd;
sbd_lu_props_t *sbdProps;
int ioctlRet;
int savedErrno;
int sbdPropsSize = sizeof (*sbdProps) + MAX_SBD_PROPS;
stmf_iocdata_t sbdIoctl = {0};
if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
*hdl = calloc(1, sizeof (luResourceImpl));
if (*hdl == NULL) {
(void) close(fd);
return (STMF_ERROR_NOMEM);
}
sbdProps = calloc(1, sbdPropsSize);
if (sbdProps == NULL) {
free(*hdl);
(void) close(fd);
return (STMF_ERROR_NOMEM);
}
ret = createDiskResource((luResourceImpl *)*hdl);
if (ret != STMF_STATUS_SUCCESS) {
free(*hdl);
free(sbdProps);
(void) close(fd);
return (ret);
}
sbdProps->slp_input_guid = 1;
bcopy(luGuid, sbdProps->slp_guid, sizeof (sbdProps->slp_guid));
sbdIoctl.stmf_version = STMF_VERSION_1;
sbdIoctl.stmf_ibuf_size = sbdPropsSize;
sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdProps;
sbdIoctl.stmf_obuf_size = sbdPropsSize;
sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdProps;
ioctlRet = ioctl(fd, SBD_IOCTL_GET_LU_PROPS, &sbdIoctl);
if (ioctlRet != 0) {
savedErrno = errno;
switch (savedErrno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
case ENOENT:
ret = STMF_ERROR_NOT_FOUND;
break;
default:
syslog(LOG_DEBUG,
"getDiskAllProps:ioctl error(%d) (%d) (%d)",
ioctlRet, sbdIoctl.stmf_error, savedErrno);
ret = STMF_STATUS_ERROR;
break;
}
}
if (ret == STMF_STATUS_SUCCESS) {
ret = loadDiskPropsFromDriver((luResourceImpl *)*hdl, sbdProps);
}
free(sbdProps);
(void) close(fd);
return (ret);
}
static int
loadDiskPropsFromDriver(luResourceImpl *hdl, sbd_lu_props_t *sbdProps)
{
int ret = STMF_STATUS_SUCCESS;
diskResource *diskLu = hdl->resource;
diskLu->luGuidValid = B_TRUE;
bcopy(sbdProps->slp_guid, diskLu->luGuid, sizeof (sbdProps->slp_guid));
if (sbdProps->slp_separate_meta && sbdProps->slp_meta_fname_valid) {
diskLu->luMetaFileNameValid = B_TRUE;
if (strlcpy(diskLu->luMetaFileName,
(char *)&(sbdProps->slp_buf[sbdProps->slp_meta_fname_off]),
sizeof (diskLu->luMetaFileName)) >=
sizeof (diskLu->luMetaFileName)) {
return (STMF_STATUS_ERROR);
}
}
if (sbdProps->slp_data_fname_valid) {
diskLu->luDataFileNameValid = B_TRUE;
if (strlcpy(diskLu->luDataFileName,
(char *)&(sbdProps->slp_buf[sbdProps->slp_data_fname_off]),
sizeof (diskLu->luDataFileName)) >=
sizeof (diskLu->luDataFileName)) {
return (STMF_STATUS_ERROR);
}
}
if (sbdProps->slp_serial_valid) {
diskLu->serialNumValid = B_TRUE;
bcopy(&(sbdProps->slp_buf[sbdProps->slp_serial_off]),
diskLu->serialNum, sbdProps->slp_serial_size);
}
if (sbdProps->slp_mgmt_url_valid) {
diskLu->luMgmtUrlValid = B_TRUE;
if (strlcpy(diskLu->luMgmtUrl,
(char *)&(sbdProps->slp_buf[sbdProps->slp_mgmt_url_off]),
sizeof (diskLu->luMgmtUrl)) >=
sizeof (diskLu->luMgmtUrl)) {
return (STMF_STATUS_ERROR);
}
}
if (sbdProps->slp_alias_valid) {
diskLu->luAliasValid = B_TRUE;
if (strlcpy(diskLu->luAlias,
(char *)&(sbdProps->slp_buf[sbdProps->slp_alias_off]),
sizeof (diskLu->luAlias)) >=
sizeof (diskLu->luAlias)) {
return (STMF_STATUS_ERROR);
}
} else {
if (sbdProps->slp_data_fname_valid) {
diskLu->luAliasValid = B_TRUE;
if (strlcpy(diskLu->luAlias,
(char *)&(sbdProps->slp_buf[
sbdProps->slp_data_fname_off]),
sizeof (diskLu->luAlias)) >=
sizeof (diskLu->luAlias)) {
return (STMF_STATUS_ERROR);
}
}
}
diskLu->vidValid = B_TRUE;
bcopy(sbdProps->slp_vid, diskLu->vid, sizeof (diskLu->vid));
diskLu->pidValid = B_TRUE;
bcopy(sbdProps->slp_pid, diskLu->pid, sizeof (diskLu->pid));
diskLu->revValid = B_TRUE;
bcopy(sbdProps->slp_rev, diskLu->rev, sizeof (diskLu->rev));
diskLu->writeProtectEnableValid = B_TRUE;
if (sbdProps->slp_write_protected) {
diskLu->writeProtectEnable = B_TRUE;
}
diskLu->writebackCacheDisableValid = B_TRUE;
if (sbdProps->slp_writeback_cache_disable_cur) {
diskLu->writebackCacheDisable = B_TRUE;
}
diskLu->blkSizeValid = B_TRUE;
diskLu->blkSize = sbdProps->slp_blksize;
diskLu->luSizeValid = B_TRUE;
diskLu->luSize = sbdProps->slp_lu_size;
diskLu->accessState = sbdProps->slp_access_state;
return (ret);
}
int
stmfGetGlobalLuProp(uint16_t dType, uint32_t prop, char *propVal,
size_t *propLen)
{
int ret = STMF_STATUS_SUCCESS;
if (dType != STMF_DISK || propVal == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
ret = getDiskGlobalProp(prop, propVal, propLen);
return (ret);
}
static int
getDiskGlobalProp(uint32_t prop, char *propVal, size_t *propLen)
{
int ret = STMF_STATUS_SUCCESS;
int fd;
sbd_global_props_t *sbdProps;
void *sbd_realloc;
int retryCnt = 0;
boolean_t retry;
int ioctlRet;
int savedErrno;
int sbdPropsSize = sizeof (*sbdProps) + MAX_SBD_PROPS;
stmf_iocdata_t sbdIoctl = {0};
size_t reqLen;
switch (prop) {
case STMF_LU_PROP_MGMT_URL:
break;
default:
return (STMF_ERROR_INVALID_PROP);
}
if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
sbdProps = calloc(1, sbdPropsSize);
if (sbdProps == NULL) {
(void) close(fd);
return (STMF_ERROR_NOMEM);
}
do {
retry = B_FALSE;
sbdIoctl.stmf_version = STMF_VERSION_1;
sbdIoctl.stmf_obuf_size = sbdPropsSize;
sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdProps;
ioctlRet = ioctl(fd, SBD_IOCTL_GET_GLOBAL_LU, &sbdIoctl);
if (ioctlRet != 0) {
savedErrno = errno;
switch (savedErrno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
case ENOMEM:
if (sbdIoctl.stmf_error ==
SBD_RET_INSUFFICIENT_BUF_SPACE &&
retryCnt++ < 3) {
sbdPropsSize =
sizeof (*sbdProps) +
sbdProps->
mlu_buf_size_needed;
sbd_realloc = sbdProps;
sbdProps = realloc(sbdProps,
sbdPropsSize);
if (sbdProps == NULL) {
free(sbd_realloc);
ret = STMF_ERROR_NOMEM;
break;
}
retry = B_TRUE;
} else {
ret = STMF_ERROR_NOMEM;
}
break;
default:
syslog(LOG_DEBUG,
"getDiskGlobalProp:ioctl error(%d)"
"(%d)(%d)", ioctlRet,
sbdIoctl.stmf_error, savedErrno);
ret = STMF_STATUS_ERROR;
break;
}
}
} while (retry);
if (ret != STMF_STATUS_SUCCESS) {
goto done;
}
switch (prop) {
case STMF_LU_PROP_MGMT_URL:
if (sbdProps->mlu_mgmt_url_valid == 0) {
ret = STMF_ERROR_NO_PROP;
goto done;
}
if ((reqLen = strlcpy(propVal, (char *)&(
sbdProps->mlu_buf[sbdProps->mlu_mgmt_url_off]),
*propLen)) >= *propLen) {
*propLen = reqLen + 1;
ret = STMF_ERROR_INVALID_ARG;
goto done;
}
break;
}
done:
free(sbdProps);
(void) close(fd);
return (ret);
}
int
stmfSetGlobalLuProp(uint16_t dType, uint32_t prop, const char *propVal)
{
int ret = STMF_STATUS_SUCCESS;
if (dType != STMF_DISK || propVal == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
ret = setDiskGlobalProp(prop, propVal);
return (ret);
}
static int
setDiskGlobalProp(uint32_t resourceProp, const char *propVal)
{
int ret = STMF_STATUS_SUCCESS;
sbd_global_props_t *sbdGlobalProps = NULL;
int sbdGlobalPropsSize = 0;
int propLen;
int mluBufSize = 0;
int fd;
int savedErrno;
int ioctlRet;
stmf_iocdata_t sbdIoctl = {0};
switch (resourceProp) {
case STMF_LU_PROP_MGMT_URL:
break;
default:
return (STMF_ERROR_INVALID_PROP);
}
if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
propLen = strlen(propVal);
mluBufSize += propLen + 1;
sbdGlobalPropsSize += sizeof (sbd_global_props_t) - 8 +
max(8, mluBufSize);
sbdGlobalProps = (sbd_global_props_t *)calloc(1, sbdGlobalPropsSize);
if (sbdGlobalProps == NULL) {
(void) close(fd);
return (STMF_ERROR_NOMEM);
}
sbdGlobalProps->mlu_struct_size = sbdGlobalPropsSize;
switch (resourceProp) {
case STMF_LU_PROP_MGMT_URL:
sbdGlobalProps->mlu_mgmt_url_valid = 1;
bcopy(propVal, &(sbdGlobalProps->mlu_buf),
propLen + 1);
break;
default:
ret = STMF_ERROR_NO_PROP;
goto done;
}
sbdIoctl.stmf_version = STMF_VERSION_1;
sbdIoctl.stmf_ibuf_size = sbdGlobalProps->mlu_struct_size;
sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdGlobalProps;
ioctlRet = ioctl(fd, SBD_IOCTL_SET_GLOBAL_LU, &sbdIoctl);
if (ioctlRet != 0) {
savedErrno = errno;
switch (savedErrno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
default:
diskError(sbdIoctl.stmf_error, &ret);
if (ret == STMF_STATUS_ERROR) {
syslog(LOG_DEBUG,
"modifyDiskLu:ioctl "
"error(%d) (%d) (%d)", ioctlRet,
sbdIoctl.stmf_error, savedErrno);
}
break;
}
}
done:
free(sbdGlobalProps);
(void) close(fd);
return (ret);
}
int
stmfSetLuProp(luResource hdl, uint32_t prop, const char *propVal)
{
int ret = STMF_STATUS_SUCCESS;
luResourceImpl *luPropsHdl = hdl;
if (hdl == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
if (luPropsHdl->type == STMF_DISK) {
ret = setDiskProp(luPropsHdl, prop, propVal);
} else {
return (STMF_ERROR_INVALID_ARG);
}
return (ret);
}
static int
getDiskProp(luResourceImpl *hdl, uint32_t prop, char *propVal, size_t *propLen)
{
int ret = STMF_STATUS_SUCCESS;
diskResource *diskLu = hdl->resource;
char accessState[20];
size_t reqLen;
if (prop == STMF_LU_PROP_ACCESS_STATE) {
if (diskLu->accessState == SBD_LU_ACTIVE) {
(void) strlcpy(accessState, STMF_ACCESS_ACTIVE,
sizeof (accessState));
} else if (diskLu->accessState == SBD_LU_TRANSITION_TO_ACTIVE) {
(void) strlcpy(accessState,
STMF_ACCESS_STANDBY_TO_ACTIVE,
sizeof (accessState));
} else if (diskLu->accessState == SBD_LU_STANDBY) {
(void) strlcpy(accessState, STMF_ACCESS_STANDBY,
sizeof (accessState));
} else if (diskLu->accessState ==
SBD_LU_TRANSITION_TO_STANDBY) {
(void) strlcpy(accessState,
STMF_ACCESS_ACTIVE_TO_STANDBY,
sizeof (accessState));
}
if ((reqLen = strlcpy(propVal, accessState,
*propLen)) >= *propLen) {
*propLen = reqLen + 1;
return (STMF_ERROR_INVALID_ARG);
}
return (0);
}
if (diskLu->accessState != SBD_LU_ACTIVE) {
return (STMF_ERROR_NO_PROP_STANDBY);
}
switch (prop) {
case STMF_LU_PROP_BLOCK_SIZE:
if (diskLu->blkSizeValid == B_FALSE) {
return (STMF_ERROR_NO_PROP);
}
reqLen = snprintf(propVal, *propLen, "%llu",
(u_longlong_t)diskLu->blkSize);
if (reqLen >= *propLen) {
*propLen = reqLen + 1;
return (STMF_ERROR_INVALID_ARG);
}
break;
case STMF_LU_PROP_FILENAME:
if (diskLu->luDataFileNameValid == B_FALSE) {
return (STMF_ERROR_NO_PROP);
}
if ((reqLen = strlcpy(propVal, diskLu->luDataFileName,
*propLen)) >= *propLen) {
*propLen = reqLen + 1;
return (STMF_ERROR_INVALID_ARG);
}
break;
case STMF_LU_PROP_META_FILENAME:
if (diskLu->luMetaFileNameValid == B_FALSE) {
return (STMF_ERROR_NO_PROP);
}
if ((reqLen = strlcpy(propVal, diskLu->luMetaFileName,
*propLen)) >= *propLen) {
*propLen = reqLen + 1;
return (STMF_ERROR_INVALID_ARG);
}
break;
case STMF_LU_PROP_MGMT_URL:
if (diskLu->luMgmtUrlValid == B_FALSE) {
return (STMF_ERROR_NO_PROP);
}
if ((reqLen = strlcpy(propVal, diskLu->luMgmtUrl,
*propLen)) >= *propLen) {
*propLen = reqLen + 1;
return (STMF_ERROR_INVALID_ARG);
}
break;
case STMF_LU_PROP_GUID:
if (diskLu->luGuidValid == B_FALSE) {
return (STMF_ERROR_NO_PROP);
}
reqLen = snprintf(propVal, *propLen,
"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X"
"%02X%02X%02X%02X",
diskLu->luGuid[0], diskLu->luGuid[1],
diskLu->luGuid[2], diskLu->luGuid[3],
diskLu->luGuid[4], diskLu->luGuid[5],
diskLu->luGuid[6], diskLu->luGuid[7],
diskLu->luGuid[8], diskLu->luGuid[9],
diskLu->luGuid[10], diskLu->luGuid[11],
diskLu->luGuid[12], diskLu->luGuid[13],
diskLu->luGuid[14], diskLu->luGuid[15]);
if (reqLen >= *propLen) {
*propLen = reqLen + 1;
return (STMF_ERROR_INVALID_ARG);
}
break;
case STMF_LU_PROP_SERIAL_NUM:
if (diskLu->serialNumValid == B_FALSE) {
return (STMF_ERROR_NO_PROP);
}
if ((reqLen = strlcpy(propVal, diskLu->serialNum,
*propLen)) >= *propLen) {
*propLen = reqLen + 1;
return (STMF_ERROR_INVALID_ARG);
}
break;
case STMF_LU_PROP_SIZE:
if (diskLu->luSizeValid == B_FALSE) {
return (STMF_ERROR_NO_PROP);
}
(void) snprintf(propVal, *propLen, "%llu",
(u_longlong_t)diskLu->luSize);
break;
case STMF_LU_PROP_ALIAS:
if (diskLu->luAliasValid == B_FALSE) {
return (STMF_ERROR_NO_PROP);
}
if ((reqLen = strlcpy(propVal, diskLu->luAlias,
*propLen)) >= *propLen) {
*propLen = reqLen + 1;
return (STMF_ERROR_INVALID_ARG);
}
break;
case STMF_LU_PROP_VID:
if (diskLu->vidValid == B_FALSE) {
return (STMF_ERROR_NO_PROP);
}
if (*propLen <= sizeof (diskLu->vid)) {
return (STMF_ERROR_INVALID_ARG);
}
bcopy(diskLu->vid, propVal, sizeof (diskLu->vid));
propVal[sizeof (diskLu->vid)] = 0;
break;
case STMF_LU_PROP_PID:
if (diskLu->pidValid == B_FALSE) {
return (STMF_ERROR_NO_PROP);
}
if (*propLen <= sizeof (diskLu->pid)) {
return (STMF_ERROR_INVALID_ARG);
}
bcopy(diskLu->pid, propVal, sizeof (diskLu->pid));
propVal[sizeof (diskLu->pid)] = 0;
break;
case STMF_LU_PROP_WRITE_PROTECT:
if (diskLu->writeProtectEnableValid == B_FALSE) {
return (STMF_ERROR_NO_PROP);
}
if (diskLu->writeProtectEnable) {
if ((reqLen = strlcpy(propVal, "true",
*propLen)) >= *propLen) {
*propLen = reqLen + 1;
return (STMF_ERROR_INVALID_ARG);
}
} else {
if ((reqLen = strlcpy(propVal, "false",
*propLen)) >= *propLen) {
*propLen = reqLen + 1;
return (STMF_ERROR_INVALID_ARG);
}
}
break;
case STMF_LU_PROP_WRITE_CACHE_DISABLE:
if (diskLu->writebackCacheDisableValid == B_FALSE) {
return (STMF_ERROR_NO_PROP);
}
if (diskLu->writebackCacheDisable) {
if ((reqLen = strlcpy(propVal, "true",
*propLen)) >= *propLen) {
*propLen = reqLen + 1;
return (STMF_ERROR_INVALID_ARG);
}
} else {
if ((reqLen = strlcpy(propVal, "false",
*propLen)) >= *propLen) {
*propLen = reqLen + 1;
return (STMF_ERROR_INVALID_ARG);
}
}
break;
default:
ret = STMF_ERROR_INVALID_PROP;
break;
}
return (ret);
}
static int
setDiskProp(luResourceImpl *hdl, uint32_t resourceProp, const char *propVal)
{
int ret = STMF_STATUS_SUCCESS;
int i;
diskResource *diskLu = hdl->resource;
unsigned long long numericProp = 0;
char guidProp[LU_ASCII_GUID_SIZE + 1];
char ouiProp[OUI_ASCII_SIZE + 1];
char hostIdProp[HOST_ID_ASCII_SIZE + 1];
unsigned int oui[OUI_SIZE];
unsigned int hostId[HOST_ID_SIZE];
unsigned int guid[LU_GUID_SIZE];
int propSize;
if (propVal == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
switch (resourceProp) {
case STMF_LU_PROP_ALIAS:
if (strlcpy(diskLu->luAlias, propVal,
sizeof (diskLu->luAlias)) >=
sizeof (diskLu->luAlias)) {
return (STMF_ERROR_INVALID_PROPSIZE);
}
diskLu->luAliasValid = B_TRUE;
break;
case STMF_LU_PROP_BLOCK_SIZE: {
const char *tmp = propVal;
while (*tmp) {
if (!isdigit(*tmp++)) {
return (STMF_ERROR_INVALID_ARG);
}
}
(void) sscanf(propVal, "%llu", &numericProp);
if (numericProp > UINT16_MAX) {
return (STMF_ERROR_INVALID_PROPSIZE);
}
diskLu->blkSize = numericProp;
diskLu->blkSizeValid = B_TRUE;
break;
}
case STMF_LU_PROP_COMPANY_ID:
if ((strlcpy(ouiProp, propVal, sizeof (ouiProp))) >=
sizeof (ouiProp)) {
return (STMF_ERROR_INVALID_ARG);
}
if (checkHexUpper(ouiProp) != 0) {
return (STMF_ERROR_INVALID_ARG);
}
(void) sscanf(ouiProp, "%2X%2X%2X",
&oui[0], &oui[1], &oui[2]);
diskLu->companyId = 0;
diskLu->companyId += oui[0] << 16;
diskLu->companyId += oui[1] << 8;
diskLu->companyId += oui[2];
if (diskLu->companyId == 0) {
return (STMF_ERROR_INVALID_ARG);
}
diskLu->companyIdValid = B_TRUE;
break;
case STMF_LU_PROP_HOST_ID:
if ((strlcpy(hostIdProp, propVal,
sizeof (hostIdProp))) >= sizeof (hostIdProp)) {
return (STMF_ERROR_INVALID_ARG);
}
if (checkHexUpper(hostIdProp) != 0) {
return (STMF_ERROR_INVALID_ARG);
}
(void) sscanf(hostIdProp, "%2X%2X%2X%2X",
&hostId[0], &hostId[1], &hostId[2], &hostId[3]);
diskLu->hostId = 0;
diskLu->hostId += hostId[0] << 24;
diskLu->hostId += hostId[1] << 16;
diskLu->hostId += hostId[2] << 8;
diskLu->hostId += hostId[3];
if (diskLu->hostId == 0) {
return (STMF_ERROR_INVALID_ARG);
}
diskLu->hostIdValid = B_TRUE;
break;
case STMF_LU_PROP_GUID:
if (strlen(propVal) != LU_ASCII_GUID_SIZE) {
return (STMF_ERROR_INVALID_PROPSIZE);
}
if ((strlcpy(guidProp, propVal, sizeof (guidProp))) >=
sizeof (guidProp)) {
return (STMF_ERROR_INVALID_ARG);
}
if (checkHexUpper(guidProp) != 0) {
return (STMF_ERROR_INVALID_ARG);
}
(void) sscanf(guidProp,
"%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X",
&guid[0], &guid[1], &guid[2], &guid[3], &guid[4],
&guid[5], &guid[6], &guid[7], &guid[8], &guid[9],
&guid[10], &guid[11], &guid[12], &guid[13],
&guid[14], &guid[15]);
for (i = 0; i < sizeof (diskLu->luGuid); i++) {
diskLu->luGuid[i] = guid[i];
}
diskLu->luGuidValid = B_TRUE;
break;
case STMF_LU_PROP_FILENAME:
if ((strlcpy(diskLu->luDataFileName, propVal,
sizeof (diskLu->luDataFileName))) >=
sizeof (diskLu->luDataFileName)) {
return (STMF_ERROR_INVALID_PROPSIZE);
}
diskLu->luDataFileNameValid = B_TRUE;
break;
case STMF_LU_PROP_META_FILENAME:
if ((strlcpy(diskLu->luMetaFileName, propVal,
sizeof (diskLu->luMetaFileName))) >=
sizeof (diskLu->luMetaFileName)) {
return (STMF_ERROR_INVALID_PROPSIZE);
}
diskLu->luMetaFileNameValid = B_TRUE;
break;
case STMF_LU_PROP_MGMT_URL:
if ((strlcpy(diskLu->luMgmtUrl, propVal,
sizeof (diskLu->luMgmtUrl))) >=
sizeof (diskLu->luMgmtUrl)) {
return (STMF_ERROR_INVALID_PROPSIZE);
}
diskLu->luMgmtUrlValid = B_TRUE;
break;
case STMF_LU_PROP_PID:
if ((propSize = strlen(propVal)) >
sizeof (diskLu->pid)) {
return (STMF_ERROR_INVALID_PROPSIZE);
}
(void) strncpy(diskLu->pid, propVal, propSize);
diskLu->pidValid = B_TRUE;
break;
case STMF_LU_PROP_SERIAL_NUM:
if ((propSize = strlen(propVal)) >
(sizeof (diskLu->serialNum) - 1)) {
return (STMF_ERROR_INVALID_PROPSIZE);
}
(void) strncpy(diskLu->serialNum, propVal, propSize);
diskLu->serialNumValid = B_TRUE;
break;
case STMF_LU_PROP_SIZE:
if ((niceStrToNum(propVal, &diskLu->luSize) != 0)) {
return (STMF_ERROR_INVALID_ARG);
}
diskLu->luSizeValid = B_TRUE;
break;
case STMF_LU_PROP_VID:
if ((propSize = strlen(propVal)) >
sizeof (diskLu->vid)) {
return (STMF_ERROR_INVALID_PROPSIZE);
}
(void) strncpy(diskLu->vid, propVal, propSize);
diskLu->vidValid = B_TRUE;
break;
case STMF_LU_PROP_WRITE_PROTECT:
if (strcasecmp(propVal, "TRUE") == 0) {
diskLu->writeProtectEnable = B_TRUE;
} else if (strcasecmp(propVal, "FALSE") == 0) {
diskLu->writeProtectEnable = B_FALSE;
} else {
return (STMF_ERROR_INVALID_ARG);
}
diskLu->writeProtectEnableValid = B_TRUE;
break;
case STMF_LU_PROP_WRITE_CACHE_DISABLE:
if (strcasecmp(propVal, "TRUE") == 0) {
diskLu->writebackCacheDisable = B_TRUE;
} else if (strcasecmp(propVal, "FALSE") == 0) {
diskLu->writebackCacheDisable = B_FALSE;
} else {
return (STMF_ERROR_INVALID_ARG);
}
diskLu->writebackCacheDisableValid = B_TRUE;
break;
case STMF_LU_PROP_ACCESS_STATE:
ret = STMF_ERROR_INVALID_PROP;
break;
default:
ret = STMF_ERROR_INVALID_PROP;
break;
}
return (ret);
}
static int
checkHexUpper(char *buf)
{
int i;
for (i = 0; i < strlen(buf); i++) {
if (isxdigit(buf[i])) {
buf[i] = toupper(buf[i]);
continue;
}
return (-1);
}
return (0);
}
static int
strToShift(const char *buf)
{
const char *ends = "BKMGTPE";
int i;
if (buf[0] == '\0')
return (0);
for (i = 0; i < strlen(ends); i++) {
if (toupper(buf[0]) == ends[i])
return (10*i);
}
return (-1);
}
int
stmfFreeLuResource(luResource hdl)
{
int ret = STMF_STATUS_SUCCESS;
if (hdl == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
luResourceImpl *hdlImpl = hdl;
free(hdlImpl->resource);
free(hdlImpl);
return (ret);
}
static int
niceStrToNum(const char *value, uint64_t *num)
{
char *end;
int shift;
*num = 0;
if ((value[0] < '0' || value[0] > '9') && value[0] != '.') {
return (-1);
}
errno = 0;
*num = strtoull(value, &end, 10);
if (errno == ERANGE) {
return (-1);
}
if (*end == '.') {
double fval = strtod(value, &end);
if ((shift = strToShift(end)) == -1) {
return (-1);
}
fval *= pow(2, shift);
if (fval > UINT64_MAX) {
return (-1);
}
*num = (uint64_t)fval;
} else {
if ((shift = strToShift(end)) == -1) {
return (-1);
}
if (shift >= 64 || (*num << shift) >> shift != *num) {
return (-1);
}
*num <<= shift;
}
return (0);
}
int
stmfCreateTargetGroup(stmfGroupName *targetGroupName)
{
int ret;
int fd;
if (targetGroupName == NULL ||
(strnlen((char *)targetGroupName, sizeof (stmfGroupName))
== sizeof (stmfGroupName))) {
return (STMF_ERROR_INVALID_ARG);
}
if (psCheckService() != STMF_STATUS_SUCCESS) {
return (STMF_ERROR_SERVICE_NOT_FOUND);
}
ret = initializeConfig();
if (ret != STMF_STATUS_SUCCESS) {
return (ret);
}
if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_TARGET_GROUP,
targetGroupName)) != STMF_STATUS_SUCCESS) {
goto done;
}
if (iGetPersistMethod() == STMF_PERSIST_NONE) {
goto done;
}
ret = psCreateTargetGroup((char *)targetGroupName);
switch (ret) {
case STMF_PS_SUCCESS:
ret = STMF_STATUS_SUCCESS;
break;
case STMF_PS_ERROR_EXISTS:
ret = STMF_ERROR_EXISTS;
break;
case STMF_PS_ERROR_BUSY:
ret = STMF_ERROR_BUSY;
break;
case STMF_PS_ERROR_SERVICE_NOT_FOUND:
ret = STMF_ERROR_SERVICE_NOT_FOUND;
break;
case STMF_PS_ERROR_VERSION_MISMATCH:
ret = STMF_ERROR_SERVICE_DATA_VERSION;
break;
default:
syslog(LOG_DEBUG,
"stmfCreateTargetGroup:psCreateTargetGroup"
":error(%d)", ret);
ret = STMF_STATUS_ERROR;
break;
}
done:
(void) close(fd);
return (ret);
}
int
stmfDeleteHostGroup(stmfGroupName *hostGroupName)
{
int ret;
int fd;
if (hostGroupName == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
if (psCheckService() != STMF_STATUS_SUCCESS) {
return (STMF_ERROR_SERVICE_NOT_FOUND);
}
ret = initializeConfig();
if (ret != STMF_STATUS_SUCCESS) {
return (ret);
}
if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
if ((ret = groupIoctl(fd, STMF_IOCTL_REMOVE_HOST_GROUP,
hostGroupName)) != STMF_STATUS_SUCCESS) {
goto done;
}
if (iGetPersistMethod() == STMF_PERSIST_NONE) {
goto done;
}
ret = psDeleteHostGroup((char *)hostGroupName);
switch (ret) {
case STMF_PS_SUCCESS:
ret = STMF_STATUS_SUCCESS;
break;
case STMF_PS_ERROR_NOT_FOUND:
ret = STMF_ERROR_NOT_FOUND;
break;
case STMF_PS_ERROR_BUSY:
ret = STMF_ERROR_BUSY;
break;
case STMF_PS_ERROR_SERVICE_NOT_FOUND:
ret = STMF_ERROR_SERVICE_NOT_FOUND;
break;
case STMF_PS_ERROR_VERSION_MISMATCH:
ret = STMF_ERROR_SERVICE_DATA_VERSION;
break;
default:
syslog(LOG_DEBUG,
"stmfDeleteHostGroup:psDeleteHostGroup:error(%d)",
ret);
ret = STMF_STATUS_ERROR;
break;
}
done:
(void) close(fd);
return (ret);
}
int
stmfDeleteTargetGroup(stmfGroupName *targetGroupName)
{
int ret = STMF_STATUS_SUCCESS;
int fd;
if (targetGroupName == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
if (psCheckService() != STMF_STATUS_SUCCESS) {
return (STMF_ERROR_SERVICE_NOT_FOUND);
}
ret = initializeConfig();
if (ret != STMF_STATUS_SUCCESS) {
return (ret);
}
if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
if ((ret = groupIoctl(fd, STMF_IOCTL_REMOVE_TARGET_GROUP,
targetGroupName)) != STMF_STATUS_SUCCESS) {
goto done;
}
if (iGetPersistMethod() == STMF_PERSIST_NONE) {
goto done;
}
ret = psDeleteTargetGroup((char *)targetGroupName);
switch (ret) {
case STMF_PS_SUCCESS:
ret = STMF_STATUS_SUCCESS;
break;
case STMF_PS_ERROR_NOT_FOUND:
ret = STMF_ERROR_NOT_FOUND;
break;
case STMF_PS_ERROR_BUSY:
ret = STMF_ERROR_BUSY;
break;
case STMF_PS_ERROR_SERVICE_NOT_FOUND:
ret = STMF_ERROR_SERVICE_NOT_FOUND;
break;
case STMF_PS_ERROR_VERSION_MISMATCH:
ret = STMF_ERROR_SERVICE_DATA_VERSION;
break;
default:
syslog(LOG_DEBUG,
"stmfDeleteTargetGroup:psDeleteTargetGroup"
":error(%d)", ret);
ret = STMF_STATUS_ERROR;
break;
}
done:
(void) close(fd);
return (ret);
}
int
stmfDevidFromIscsiName(char *iscsiName, stmfDevid *devid)
{
if (devid == NULL || iscsiName == NULL)
return (STMF_ERROR_INVALID_ARG);
bzero(devid, sizeof (stmfDevid));
if ((devid->identLength = strlen(iscsiName)) > MAX_ISCSI_NAME ||
devid->identLength < strlen(EUI) ||
devid->identLength < strlen(IQN)) {
return (STMF_ERROR_INVALID_ARG);
}
if ((strncmp(iscsiName, EUI, strlen(EUI)) != 0) &&
strncmp(iscsiName, IQN, strlen(IQN)) != 0) {
return (STMF_ERROR_INVALID_ARG);
}
bcopy(iscsiName, devid->ident, devid->identLength);
return (STMF_STATUS_SUCCESS);
}
int
stmfDevidFromWwn(uchar_t wwn[8], stmfDevid *devid)
{
if (wwn == NULL || devid == NULL)
return (STMF_ERROR_INVALID_ARG);
bzero(devid, sizeof (stmfDevid));
(void) bcopy(WWN, devid->ident, strlen(WWN));
(void) snprintf((char *)&devid->ident[strlen(WWN)],
sizeof (devid->ident), "%02X%02X%02X%02X%02X%02X%02X%02X",
wwn[0], wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]);
devid->identLength = strlen((char *)devid->ident);
return (STMF_STATUS_SUCCESS);
}
void
stmfFreeMemory(void *memory)
{
free(memory);
}
static int
groupListIoctl(stmfGroupList **groupList, int groupType)
{
int ret;
int fd;
int ioctlRet;
int i;
int cmd;
stmf_iocdata_t stmfIoctl;
stmf_group_name_t *iGroupList = NULL;
uint32_t groupListSize;
if (groupList == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
if (groupType == HOST_GROUP) {
cmd = STMF_IOCTL_GET_HG_LIST;
} else if (groupType == TARGET_GROUP) {
cmd = STMF_IOCTL_GET_TG_LIST;
} else {
return (STMF_ERROR_INVALID_ARG);
}
ret = initializeConfig();
if (ret != STMF_STATUS_SUCCESS) {
return (ret);
}
if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
groupListSize = ALLOC_GROUP;
groupListSize = groupListSize * (sizeof (stmf_group_name_t));
iGroupList = (stmf_group_name_t *)calloc(1, groupListSize);
if (iGroupList == NULL) {
ret = STMF_ERROR_NOMEM;
goto done;
}
bzero(&stmfIoctl, sizeof (stmfIoctl));
stmfIoctl.stmf_version = STMF_VERSION_1;
stmfIoctl.stmf_obuf_size = groupListSize;
stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupList;
ioctlRet = ioctl(fd, cmd, &stmfIoctl);
if (ioctlRet != 0) {
switch (errno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
default:
syslog(LOG_DEBUG,
"groupListIoctl:ioctl errno(%d)",
errno);
ret = STMF_STATUS_ERROR;
break;
}
goto done;
}
if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_GROUP) {
groupListSize = stmfIoctl.stmf_obuf_max_nentries *
sizeof (stmf_group_name_t);
iGroupList = realloc(iGroupList, groupListSize);
if (iGroupList == NULL) {
ret = STMF_ERROR_NOMEM;
goto done;
}
stmfIoctl.stmf_obuf_size = groupListSize;
stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupList;
ioctlRet = ioctl(fd, cmd, &stmfIoctl);
if (ioctlRet != 0) {
switch (errno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
default:
syslog(LOG_DEBUG,
"groupListIoctl:ioctl errno(%d)",
errno);
ret = STMF_STATUS_ERROR;
break;
}
goto done;
}
}
*groupList = (stmfGroupList *)calloc(1, sizeof (stmfGroupList) +
sizeof (stmfGroupName) * stmfIoctl.stmf_obuf_nentries);
if (*groupList == NULL) {
ret = STMF_ERROR_NOMEM;
goto done;
}
(*groupList)->cnt = stmfIoctl.stmf_obuf_nentries;
for (i = 0; i < stmfIoctl.stmf_obuf_nentries; i++) {
bcopy(iGroupList[i].name, (*groupList)->name[i],
sizeof (stmfGroupName));
}
done:
free(iGroupList);
(void) close(fd);
return (ret);
}
static int
groupMemberListIoctl(stmfGroupName *groupName, stmfGroupProperties **groupProps,
int groupType)
{
int ret;
int fd;
int ioctlRet;
int i;
int cmd;
stmf_iocdata_t stmfIoctl;
stmf_group_name_t iGroupName;
stmf_ge_ident_t *iGroupMembers;
uint32_t groupListSize;
if (groupName == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
if (groupType == HOST_GROUP) {
cmd = STMF_IOCTL_GET_HG_ENTRIES;
} else if (groupType == TARGET_GROUP) {
cmd = STMF_IOCTL_GET_TG_ENTRIES;
} else {
return (STMF_ERROR_INVALID_ARG);
}
ret = initializeConfig();
if (ret != STMF_STATUS_SUCCESS) {
return (ret);
}
if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
bzero(&iGroupName, sizeof (iGroupName));
bcopy(groupName, &iGroupName.name, strlen((char *)groupName));
iGroupName.name_size = strlen((char *)groupName);
groupListSize = ALLOC_GRP_MEMBER;
groupListSize = groupListSize * (sizeof (stmf_ge_ident_t));
iGroupMembers = (stmf_ge_ident_t *)calloc(1, groupListSize);
if (iGroupMembers == NULL) {
ret = STMF_ERROR_NOMEM;
goto done;
}
bzero(&stmfIoctl, sizeof (stmfIoctl));
stmfIoctl.stmf_version = STMF_VERSION_1;
stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&iGroupName;
stmfIoctl.stmf_ibuf_size = sizeof (stmf_group_name_t);
stmfIoctl.stmf_obuf_size = groupListSize;
stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupMembers;
ioctlRet = ioctl(fd, cmd, &stmfIoctl);
if (ioctlRet != 0) {
switch (errno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
default:
syslog(LOG_DEBUG,
"groupListIoctl:ioctl errno(%d)",
errno);
ret = STMF_STATUS_ERROR;
break;
}
goto done;
}
if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_GRP_MEMBER) {
groupListSize = stmfIoctl.stmf_obuf_max_nentries *
sizeof (stmf_ge_ident_t);
iGroupMembers = realloc(iGroupMembers, groupListSize);
if (iGroupMembers == NULL) {
ret = STMF_ERROR_NOMEM;
goto done;
}
stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&iGroupName;
stmfIoctl.stmf_ibuf_size = sizeof (stmf_group_name_t);
stmfIoctl.stmf_obuf_size = groupListSize;
stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupMembers;
ioctlRet = ioctl(fd, cmd, &stmfIoctl);
if (ioctlRet != 0) {
switch (errno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
default:
syslog(LOG_DEBUG,
"groupListIoctl:ioctl errno(%d)",
errno);
ret = STMF_STATUS_ERROR;
break;
}
goto done;
}
}
*groupProps = (stmfGroupProperties *)calloc(1,
sizeof (stmfGroupProperties) +
sizeof (stmfDevid) * stmfIoctl.stmf_obuf_nentries);
if (*groupProps == NULL) {
ret = STMF_ERROR_NOMEM;
goto done;
}
(*groupProps)->cnt = stmfIoctl.stmf_obuf_nentries;
for (i = 0; i < stmfIoctl.stmf_obuf_nentries; i++) {
(*groupProps)->name[i].identLength =
iGroupMembers[i].ident_size;
bcopy(iGroupMembers[i].ident, (*groupProps)->name[i].ident,
iGroupMembers[i].ident_size);
}
done:
free(iGroupMembers);
(void) close(fd);
return (ret);
}
static int
iLoadGroupFromPs(stmfGroupList **groupList, int type)
{
int ret;
if (groupList == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
if (type == HOST_GROUP) {
ret = psGetHostGroupList(groupList);
} else if (type == TARGET_GROUP) {
ret = psGetTargetGroupList(groupList);
} else {
return (STMF_ERROR_INVALID_ARG);
}
switch (ret) {
case STMF_PS_SUCCESS:
ret = STMF_STATUS_SUCCESS;
break;
case STMF_PS_ERROR_NOT_FOUND:
ret = STMF_ERROR_NOT_FOUND;
break;
case STMF_PS_ERROR_BUSY:
ret = STMF_ERROR_BUSY;
break;
case STMF_PS_ERROR_SERVICE_NOT_FOUND:
ret = STMF_ERROR_SERVICE_NOT_FOUND;
break;
case STMF_PS_ERROR_VERSION_MISMATCH:
ret = STMF_ERROR_SERVICE_DATA_VERSION;
break;
default:
syslog(LOG_DEBUG,
"stmfGetHostGroupList:psGetHostGroupList:error(%d)",
ret);
ret = STMF_STATUS_ERROR;
break;
}
return (ret);
}
int
stmfGetHostGroupList(stmfGroupList **hostGroupList)
{
int ret = STMF_STATUS_ERROR;
if (hostGroupList == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
ret = groupListIoctl(hostGroupList, HOST_GROUP);
return (ret);
}
static int
iLoadGroupMembersFromPs(stmfGroupName *groupName,
stmfGroupProperties **groupProp, int type)
{
int ret;
if (groupName == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
if (type == HOST_GROUP) {
ret = psGetHostGroupMemberList((char *)groupName, groupProp);
} else if (type == TARGET_GROUP) {
ret = psGetTargetGroupMemberList((char *)groupName, groupProp);
} else {
return (STMF_ERROR_INVALID_ARG);
}
switch (ret) {
case STMF_PS_SUCCESS:
ret = STMF_STATUS_SUCCESS;
break;
case STMF_PS_ERROR_NOT_FOUND:
ret = STMF_ERROR_NOT_FOUND;
break;
case STMF_PS_ERROR_BUSY:
ret = STMF_ERROR_BUSY;
break;
case STMF_PS_ERROR_SERVICE_NOT_FOUND:
ret = STMF_ERROR_SERVICE_NOT_FOUND;
break;
case STMF_PS_ERROR_VERSION_MISMATCH:
ret = STMF_ERROR_SERVICE_DATA_VERSION;
break;
default:
syslog(LOG_DEBUG,
"iLoadGroupMembersFromPs:psGetHostGroupList:"
"error(%d)", ret);
ret = STMF_STATUS_ERROR;
break;
}
return (ret);
}
int
stmfGetHostGroupMembers(stmfGroupName *groupName,
stmfGroupProperties **groupProp)
{
int ret;
if (groupName == NULL || groupProp == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
ret = groupMemberListIoctl(groupName, groupProp, HOST_GROUP);
return (ret);
}
int
stmfGetProviderData(char *providerName, nvlist_t **nvl, int providerType)
{
return (stmfGetProviderDataProt(providerName, nvl, providerType,
NULL));
}
int
stmfGetProviderDataProt(char *providerName, nvlist_t **nvl, int providerType,
uint64_t *setToken)
{
int ret;
if (providerName == NULL || nvl == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
if (providerType != STMF_LU_PROVIDER_TYPE &&
providerType != STMF_PORT_PROVIDER_TYPE) {
return (STMF_ERROR_INVALID_ARG);
}
ret = initializeConfig();
if (ret != STMF_STATUS_SUCCESS) {
return (ret);
}
return (getProviderData(providerName, nvl, providerType, setToken));
}
int
stmfGetProviderDataList(stmfProviderList **providerList)
{
int ret;
ret = psGetProviderDataList(providerList);
switch (ret) {
case STMF_PS_SUCCESS:
ret = STMF_STATUS_SUCCESS;
break;
case STMF_PS_ERROR_BUSY:
ret = STMF_ERROR_BUSY;
break;
case STMF_PS_ERROR_SERVICE_NOT_FOUND:
ret = STMF_ERROR_SERVICE_NOT_FOUND;
break;
case STMF_PS_ERROR_VERSION_MISMATCH:
ret = STMF_ERROR_SERVICE_DATA_VERSION;
break;
default:
syslog(LOG_DEBUG,
"stmfGetProviderDataList:psGetProviderDataList"
":error(%d)", ret);
ret = STMF_STATUS_ERROR;
break;
}
return (ret);
}
int
stmfGetSessionList(stmfDevid *devid, stmfSessionList **sessionList)
{
int ret = STMF_STATUS_SUCCESS;
int fd;
int ioctlRet;
int cmd = STMF_IOCTL_SESSION_LIST;
int i;
stmf_iocdata_t stmfIoctl;
slist_scsi_session_t *fSessionList, *fSessionListP = NULL;
uint8_t ident[260];
uint32_t fSessionListSize;
if (sessionList == NULL || devid == NULL) {
ret = STMF_ERROR_INVALID_ARG;
}
ret = initializeConfig();
if (ret != STMF_STATUS_SUCCESS) {
return (ret);
}
if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
fSessionListSize = ALLOC_SESSION;
fSessionListSize = fSessionListSize * (sizeof (slist_scsi_session_t));
fSessionList = (slist_scsi_session_t *)calloc(1, fSessionListSize);
fSessionListP = fSessionList;
if (fSessionList == NULL) {
ret = STMF_ERROR_NOMEM;
goto done;
}
ident[IDENT_LENGTH_BYTE] = devid->identLength;
bcopy(&(devid->ident), &ident[IDENT_LENGTH_BYTE + 1],
devid->identLength);
bzero(&stmfIoctl, sizeof (stmfIoctl));
stmfIoctl.stmf_version = STMF_VERSION_1;
stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ident;
stmfIoctl.stmf_ibuf_size = sizeof (ident);
stmfIoctl.stmf_obuf_size = fSessionListSize;
stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fSessionList;
ioctlRet = ioctl(fd, cmd, &stmfIoctl);
if (ioctlRet != 0) {
switch (errno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
default:
syslog(LOG_DEBUG,
"stmfGetSessionList:ioctl errno(%d)",
errno);
ret = STMF_STATUS_ERROR;
break;
}
goto done;
}
if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_SESSION) {
fSessionListSize = stmfIoctl.stmf_obuf_max_nentries *
sizeof (slist_scsi_session_t);
fSessionList = realloc(fSessionList, fSessionListSize);
if (fSessionList == NULL) {
ret = STMF_ERROR_NOMEM;
goto done;
}
fSessionListP = fSessionList;
stmfIoctl.stmf_obuf_size = fSessionListSize;
stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fSessionList;
ioctlRet = ioctl(fd, cmd, &stmfIoctl);
if (ioctlRet != 0) {
switch (errno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
default:
syslog(LOG_DEBUG,
"stmfGetSessionList:ioctl "
"errno(%d)", errno);
ret = STMF_STATUS_ERROR;
break;
}
goto done;
}
}
*sessionList = (stmfSessionList *)calloc(1, sizeof (stmfSessionList) +
stmfIoctl.stmf_obuf_max_nentries * sizeof (stmfSession));
if (*sessionList == NULL) {
ret = STMF_ERROR_NOMEM;
free(sessionList);
goto done;
}
(*sessionList)->cnt = stmfIoctl.stmf_obuf_max_nentries;
for (i = 0; i < (*sessionList)->cnt; i++) {
(*sessionList)->session[i].initiator.identLength =
fSessionList->initiator[IDENT_LENGTH_BYTE];
bcopy(&(fSessionList->initiator[IDENT_LENGTH_BYTE + 1]),
(*sessionList)->session[i].initiator.ident,
STMF_IDENT_LENGTH);
bcopy(&(fSessionList->alias),
&((*sessionList)->session[i].alias),
sizeof ((*sessionList)->session[i].alias));
bcopy(&(fSessionList++->creation_time),
&((*sessionList)->session[i].creationTime),
sizeof (time_t));
}
done:
(void) close(fd);
free(fSessionListP);
return (ret);
}
int
stmfGetTargetGroupList(stmfGroupList **targetGroupList)
{
int ret;
if (targetGroupList == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
ret = groupListIoctl(targetGroupList, TARGET_GROUP);
return (ret);
}
int
stmfGetTargetGroupMembers(stmfGroupName *groupName,
stmfGroupProperties **groupProp)
{
int ret;
if (groupName == NULL || groupProp == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
ret = groupMemberListIoctl(groupName, groupProp, TARGET_GROUP);
return (ret);
}
int
stmfGetTargetList(stmfDevidList **targetList)
{
int ret;
int fd;
int ioctlRet;
int i;
stmf_iocdata_t stmfIoctl;
slist_target_port_t *fTargetList, *fTargetListP = NULL;
uint32_t fTargetListSize;
if (targetList == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
ret = initializeConfig();
if (ret != STMF_STATUS_SUCCESS) {
return (ret);
}
if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
fTargetListSize = ALLOC_TARGET_PORT * sizeof (slist_target_port_t);
fTargetListP = fTargetList =
(slist_target_port_t *)calloc(1, fTargetListSize);
if (fTargetList == NULL) {
ret = STMF_ERROR_NOMEM;
goto done;
}
bzero(&stmfIoctl, sizeof (stmfIoctl));
stmfIoctl.stmf_version = STMF_VERSION_1;
stmfIoctl.stmf_obuf_size = fTargetListSize;
stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fTargetList;
ioctlRet = ioctl(fd, STMF_IOCTL_TARGET_PORT_LIST, &stmfIoctl);
if (ioctlRet != 0) {
switch (errno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
default:
syslog(LOG_DEBUG,
"stmfGetTargetList:ioctl errno(%d)", errno);
ret = STMF_STATUS_ERROR;
break;
}
goto done;
}
if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_TARGET_PORT) {
fTargetListSize = stmfIoctl.stmf_obuf_max_nentries *
sizeof (slist_target_port_t);
fTargetListP = fTargetList =
realloc(fTargetList, fTargetListSize);
if (fTargetList == NULL) {
ret = STMF_ERROR_NOMEM;
goto done;
}
stmfIoctl.stmf_obuf_size = fTargetListSize;
stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fTargetList;
ioctlRet = ioctl(fd, STMF_IOCTL_TARGET_PORT_LIST,
&stmfIoctl);
if (ioctlRet != 0) {
switch (errno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
default:
syslog(LOG_DEBUG,
"stmfGetTargetList:ioctl errno(%d)",
errno);
ret = STMF_STATUS_ERROR;
break;
}
goto done;
}
}
*targetList = (stmfDevidList *)calloc(1,
stmfIoctl.stmf_obuf_max_nentries * sizeof (stmfDevid) +
sizeof (stmfDevidList));
if (*targetList == NULL) {
ret = STMF_ERROR_NOMEM;
goto done;
}
(*targetList)->cnt = stmfIoctl.stmf_obuf_max_nentries;
for (i = 0; i < stmfIoctl.stmf_obuf_max_nentries; i++, fTargetList++) {
(*targetList)->devid[i].identLength =
fTargetList->target[IDENT_LENGTH_BYTE];
bcopy(&fTargetList->target[IDENT_LENGTH_BYTE + 1],
&(*targetList)->devid[i].ident,
fTargetList->target[IDENT_LENGTH_BYTE]);
}
done:
(void) close(fd);
free(fTargetListP);
return (ret);
}
int
stmfGetTargetProperties(stmfDevid *devid, stmfTargetProperties *targetProps)
{
int ret = STMF_STATUS_SUCCESS;
int fd;
int ioctlRet;
stmf_iocdata_t stmfIoctl;
sioc_target_port_props_t targetProperties;
scsi_devid_desc_t *scsiDevid;
if (devid == NULL || targetProps == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
ret = initializeConfig();
if (ret != STMF_STATUS_SUCCESS) {
return (ret);
}
if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
targetProperties.tgt_id[IDENT_LENGTH_BYTE] = devid->identLength;
bcopy(&(devid->ident), &targetProperties.tgt_id[IDENT_LENGTH_BYTE + 1],
devid->identLength);
bzero(&stmfIoctl, sizeof (stmfIoctl));
stmfIoctl.stmf_version = STMF_VERSION_1;
stmfIoctl.stmf_ibuf_size = sizeof (targetProperties.tgt_id);
stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&targetProperties.tgt_id;
stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&targetProperties;
stmfIoctl.stmf_obuf_size = sizeof (targetProperties);
ioctlRet = ioctl(fd, STMF_IOCTL_GET_TARGET_PORT_PROPERTIES,
&stmfIoctl);
if (ioctlRet != 0) {
switch (errno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
case ENOENT:
ret = STMF_ERROR_NOT_FOUND;
break;
default:
syslog(LOG_DEBUG,
"stmfGetTargetProperties:ioctl errno(%d)",
errno);
ret = STMF_STATUS_ERROR;
break;
}
goto done;
}
bcopy(targetProperties.tgt_provider_name, targetProps->providerName,
sizeof (targetProperties.tgt_provider_name));
if (targetProperties.tgt_state == STMF_STATE_ONLINE) {
targetProps->status = STMF_TARGET_PORT_ONLINE;
} else if (targetProperties.tgt_state == STMF_STATE_OFFLINE) {
targetProps->status = STMF_TARGET_PORT_OFFLINE;
} else if (targetProperties.tgt_state == STMF_STATE_ONLINING) {
targetProps->status = STMF_TARGET_PORT_ONLINING;
} else if (targetProperties.tgt_state == STMF_STATE_OFFLINING) {
targetProps->status = STMF_TARGET_PORT_OFFLINING;
}
bcopy(targetProperties.tgt_alias, targetProps->alias,
sizeof (targetProps->alias));
scsiDevid = (scsi_devid_desc_t *)&targetProperties.tgt_id;
targetProps->protocol = scsiDevid->protocol_id;
done:
(void) close(fd);
return (ret);
}
int
stmfGetLogicalUnitList(stmfGuidList **luList)
{
int ret;
int fd;
int ioctlRet;
int cmd = STMF_IOCTL_LU_LIST;
int i;
stmf_iocdata_t stmfIoctl;
slist_lu_t *fLuList;
uint32_t fLuListSize;
uint32_t listCnt;
if (luList == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
ret = initializeConfig();
if (ret != STMF_STATUS_SUCCESS) {
return (ret);
}
if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
fLuListSize = ALLOC_LU;
fLuListSize = fLuListSize * (sizeof (slist_lu_t));
fLuList = (slist_lu_t *)calloc(1, fLuListSize);
if (fLuList == NULL) {
ret = STMF_ERROR_NOMEM;
goto done;
}
bzero(&stmfIoctl, sizeof (stmfIoctl));
stmfIoctl.stmf_version = STMF_VERSION_1;
stmfIoctl.stmf_obuf_size = fLuListSize;
stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fLuList;
ioctlRet = ioctl(fd, cmd, &stmfIoctl);
if (ioctlRet != 0) {
switch (errno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
default:
syslog(LOG_DEBUG,
"stmfGetLogicalUnitList:ioctl errno(%d)",
errno);
ret = STMF_STATUS_ERROR;
break;
}
goto done;
}
if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_LU) {
fLuListSize = stmfIoctl.stmf_obuf_max_nentries *
sizeof (slist_lu_t);
free(fLuList);
fLuList = (slist_lu_t *)calloc(1, fLuListSize);
if (fLuList == NULL) {
ret = STMF_ERROR_NOMEM;
goto done;
}
stmfIoctl.stmf_obuf_size = fLuListSize;
stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fLuList;
ioctlRet = ioctl(fd, cmd, &stmfIoctl);
if (ioctlRet != 0) {
switch (errno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
default:
syslog(LOG_DEBUG,
"stmfGetLogicalUnitList:"
"ioctl errno(%d)", errno);
ret = STMF_STATUS_ERROR;
break;
}
goto done;
}
}
if (ret != STMF_STATUS_SUCCESS) {
goto done;
}
listCnt = stmfIoctl.stmf_obuf_nentries;
*luList = (stmfGuidList *)calloc(1, sizeof (stmfGuidList) +
listCnt * sizeof (stmfGuid));
if (*luList == NULL) {
ret = STMF_ERROR_NOMEM;
goto done;
}
(*luList)->cnt = listCnt;
for (i = 0; i < listCnt; i++) {
bcopy(&fLuList[i].lu_guid, (*luList)->guid[i].guid,
sizeof (stmfGuid));
}
qsort((void *)&((*luList)->guid[0]), (*luList)->cnt,
sizeof (stmfGuid), guidCompare);
done:
(void) close(fd);
free(fLuList);
return (ret);
}
int
stmfGetLogicalUnitProperties(stmfGuid *lu, stmfLogicalUnitProperties *luProps)
{
int ret = STMF_STATUS_SUCCESS;
int stmfRet;
int fd;
int ioctlRet;
int cmd = STMF_IOCTL_GET_LU_PROPERTIES;
stmfViewEntryList *viewEntryList = NULL;
stmf_iocdata_t stmfIoctl;
sioc_lu_props_t fLuProps;
if (lu == NULL || luProps == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
bzero(luProps, sizeof (stmfLogicalUnitProperties));
ret = initializeConfig();
if (ret != STMF_STATUS_SUCCESS) {
return (ret);
}
if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
bzero(&stmfIoctl, sizeof (stmfIoctl));
stmfIoctl.stmf_version = STMF_VERSION_1;
stmfIoctl.stmf_ibuf_size = sizeof (stmfGuid);
stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)lu;
stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&fLuProps;
stmfIoctl.stmf_obuf_size = sizeof (fLuProps);
ioctlRet = ioctl(fd, cmd, &stmfIoctl);
if (ioctlRet != 0) {
switch (errno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
case ENOENT:
stmfRet = stmfGetViewEntryList(lu,
&viewEntryList);
if (stmfRet == STMF_STATUS_SUCCESS) {
luProps->status =
STMF_LOGICAL_UNIT_UNREGISTERED;
if (viewEntryList->cnt > 0) {
ret = STMF_STATUS_SUCCESS;
} else {
ret = STMF_ERROR_NOT_FOUND;
}
} else {
ret = STMF_ERROR_NOT_FOUND;
}
stmfFreeMemory(viewEntryList);
break;
default:
syslog(LOG_DEBUG,
"stmfGetLogicalUnit:ioctl errno(%d)",
errno);
ret = STMF_STATUS_ERROR;
break;
}
goto done;
}
bcopy(fLuProps.lu_provider_name, luProps->providerName,
sizeof (fLuProps.lu_provider_name));
if (fLuProps.lu_state == STMF_STATE_ONLINE) {
luProps->status = STMF_LOGICAL_UNIT_ONLINE;
} else if (fLuProps.lu_state == STMF_STATE_OFFLINE) {
luProps->status = STMF_LOGICAL_UNIT_OFFLINE;
} else if (fLuProps.lu_state == STMF_STATE_ONLINING) {
luProps->status = STMF_LOGICAL_UNIT_ONLINING;
} else if (fLuProps.lu_state == STMF_STATE_OFFLINING) {
luProps->status = STMF_LOGICAL_UNIT_OFFLINING;
}
bcopy(fLuProps.lu_alias, luProps->alias, sizeof (luProps->alias));
done:
(void) close(fd);
return (ret);
}
int
stmfGetState(stmfState *state)
{
int ret;
stmf_state_desc_t iState;
if (state == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
ret = getStmfState(&iState);
if (ret != STMF_STATUS_SUCCESS) {
return (ret);
}
switch (iState.state) {
case STMF_STATE_ONLINE:
state->operationalState =
STMF_SERVICE_STATE_ONLINE;
break;
case STMF_STATE_OFFLINE:
state->operationalState =
STMF_SERVICE_STATE_OFFLINE;
break;
case STMF_STATE_ONLINING:
state->operationalState =
STMF_SERVICE_STATE_ONLINING;
break;
case STMF_STATE_OFFLINING:
state->operationalState =
STMF_SERVICE_STATE_OFFLINING;
break;
default:
state->operationalState =
STMF_SERVICE_STATE_UNKNOWN;
break;
}
switch (iState.config_state) {
case STMF_CONFIG_NONE:
state->configState = STMF_CONFIG_STATE_NONE;
break;
case STMF_CONFIG_INIT:
state->configState = STMF_CONFIG_STATE_INIT;
break;
case STMF_CONFIG_INIT_DONE:
state->configState =
STMF_CONFIG_STATE_INIT_DONE;
break;
default:
state->configState =
STMF_CONFIG_STATE_UNKNOWN;
break;
}
return (STMF_STATUS_SUCCESS);
}
int
stmfGetViewEntryList(stmfGuid *lu, stmfViewEntryList **viewEntryList)
{
int ret;
int fd;
int ioctlRet;
int cmd = STMF_IOCTL_LU_VE_LIST;
int i;
stmf_iocdata_t stmfIoctl;
stmf_view_op_entry_t *fVeList;
uint32_t fVeListSize;
uint32_t listCnt;
if (lu == NULL || viewEntryList == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
ret = initializeConfig();
if (ret != STMF_STATUS_SUCCESS) {
return (ret);
}
if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
fVeListSize = ALLOC_VE;
fVeListSize = fVeListSize * (sizeof (stmf_view_op_entry_t));
fVeList = (stmf_view_op_entry_t *)calloc(1, fVeListSize);
if (fVeList == NULL) {
ret = STMF_ERROR_NOMEM;
goto done;
}
bzero(&stmfIoctl, sizeof (stmfIoctl));
stmfIoctl.stmf_version = STMF_VERSION_1;
stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)lu;
stmfIoctl.stmf_ibuf_size = sizeof (stmfGuid);
stmfIoctl.stmf_obuf_size = fVeListSize;
stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fVeList;
ioctlRet = ioctl(fd, cmd, &stmfIoctl);
if (ioctlRet != 0) {
switch (errno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
default:
syslog(LOG_DEBUG,
"stmfGetViewEntryList:ioctl errno(%d)",
errno);
ret = STMF_STATUS_ERROR;
break;
}
goto done;
}
if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_VE) {
bzero(&stmfIoctl, sizeof (stmfIoctl));
fVeListSize = stmfIoctl.stmf_obuf_max_nentries *
sizeof (stmf_view_op_entry_t);
free(fVeList);
fVeList = (stmf_view_op_entry_t *)calloc(1, fVeListSize);
if (fVeList == NULL) {
return (STMF_ERROR_NOMEM);
}
stmfIoctl.stmf_obuf_size = fVeListSize;
stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fVeList;
ioctlRet = ioctl(fd, cmd, &stmfIoctl);
if (ioctlRet != 0) {
switch (errno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
default:
syslog(LOG_DEBUG,
"stmfGetLogicalUnitList:"
"ioctl errno(%d)", errno);
ret = STMF_STATUS_ERROR;
break;
}
goto done;
}
}
if (ret != STMF_STATUS_SUCCESS) {
goto done;
}
listCnt = stmfIoctl.stmf_obuf_nentries;
*viewEntryList = (stmfViewEntryList *)calloc(1,
sizeof (stmfViewEntryList) + listCnt * sizeof (stmfViewEntry));
if (*viewEntryList == NULL) {
ret = STMF_ERROR_NOMEM;
goto done;
}
(*viewEntryList)->cnt = listCnt;
for (i = 0; i < listCnt; i++) {
(*viewEntryList)->ve[i].veIndexValid = B_TRUE;
(*viewEntryList)->ve[i].veIndex = fVeList[i].ve_ndx;
if (fVeList[i].ve_all_hosts == 1) {
(*viewEntryList)->ve[i].allHosts = B_TRUE;
} else {
bcopy(fVeList[i].ve_host_group.name,
(*viewEntryList)->ve[i].hostGroup,
fVeList[i].ve_host_group.name_size);
}
if (fVeList[i].ve_all_targets == 1) {
(*viewEntryList)->ve[i].allTargets = B_TRUE;
} else {
bcopy(fVeList[i].ve_target_group.name,
(*viewEntryList)->ve[i].targetGroup,
fVeList[i].ve_target_group.name_size);
}
bcopy(fVeList[i].ve_lu_nbr, (*viewEntryList)->ve[i].luNbr,
sizeof ((*viewEntryList)->ve[i].luNbr));
(*viewEntryList)->ve[i].luNbrValid = B_TRUE;
}
qsort((void *)&((*viewEntryList)->ve[0]), (*viewEntryList)->cnt,
sizeof (stmfViewEntry), viewEntryCompare);
done:
(void) close(fd);
free(fVeList);
return (ret);
}
static int
loadHostGroups(int fd, stmfGroupList *groupList)
{
int i, j;
int ret = STMF_STATUS_SUCCESS;
stmfGroupProperties *groupProps = NULL;
for (i = 0; i < groupList->cnt; i++) {
if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_HOST_GROUP,
&(groupList->name[i]))) != STMF_STATUS_SUCCESS) {
goto out;
}
ret = iLoadGroupMembersFromPs(&(groupList->name[i]),
&groupProps, HOST_GROUP);
for (j = 0; j < groupProps->cnt; j++) {
if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_HG_ENTRY,
&(groupList->name[i]), &(groupProps->name[j])))
!= STMF_STATUS_SUCCESS) {
goto out;
}
}
}
out:
stmfFreeMemory(groupProps);
return (ret);
}
static int
loadTargetGroups(int fd, stmfGroupList *groupList)
{
int i, j;
int ret = STMF_STATUS_SUCCESS;
stmfGroupProperties *groupProps = NULL;
for (i = 0; i < groupList->cnt; i++) {
if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_TARGET_GROUP,
&(groupList->name[i]))) != STMF_STATUS_SUCCESS) {
goto out;
}
ret = iLoadGroupMembersFromPs(&(groupList->name[i]),
&groupProps, TARGET_GROUP);
for (j = 0; j < groupProps->cnt; j++) {
if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_TG_ENTRY,
&(groupList->name[i]), &(groupProps->name[j])))
!= STMF_STATUS_SUCCESS) {
goto out;
}
}
}
out:
stmfFreeMemory(groupProps);
return (ret);
}
static int
loadStore(int fd)
{
int ret;
int i, j;
stmfGroupList *groupList = NULL;
stmfGuidList *guidList = NULL;
stmfViewEntryList *viewEntryList = NULL;
stmfProviderList *providerList = NULL;
int providerType;
nvlist_t *nvl = NULL;
ret = iLoadGroupFromPs(&groupList, HOST_GROUP);
if (ret != STMF_STATUS_SUCCESS) {
return (ret);
}
ret = loadHostGroups(fd, groupList);
if (ret != STMF_STATUS_SUCCESS) {
goto out;
}
stmfFreeMemory(groupList);
groupList = NULL;
ret = iLoadGroupFromPs(&groupList, TARGET_GROUP);
if (ret != STMF_STATUS_SUCCESS) {
goto out;
}
ret = loadTargetGroups(fd, groupList);
if (ret != STMF_STATUS_SUCCESS) {
goto out;
}
stmfFreeMemory(groupList);
groupList = NULL;
ret = psGetLogicalUnitList(&guidList);
switch (ret) {
case STMF_PS_SUCCESS:
ret = STMF_STATUS_SUCCESS;
break;
case STMF_PS_ERROR_NOT_FOUND:
ret = STMF_ERROR_NOT_FOUND;
break;
case STMF_PS_ERROR_BUSY:
ret = STMF_ERROR_BUSY;
break;
case STMF_PS_ERROR_SERVICE_NOT_FOUND:
ret = STMF_ERROR_SERVICE_NOT_FOUND;
break;
case STMF_PS_ERROR_VERSION_MISMATCH:
ret = STMF_ERROR_SERVICE_DATA_VERSION;
break;
default:
ret = STMF_STATUS_ERROR;
break;
}
if (ret != STMF_STATUS_SUCCESS) {
goto out;
}
for (i = 0; i < guidList->cnt; i++) {
ret = psGetViewEntryList(&guidList->guid[i], &viewEntryList);
switch (ret) {
case STMF_PS_SUCCESS:
ret = STMF_STATUS_SUCCESS;
break;
case STMF_PS_ERROR_NOT_FOUND:
ret = STMF_ERROR_NOT_FOUND;
break;
case STMF_PS_ERROR_BUSY:
ret = STMF_ERROR_BUSY;
break;
case STMF_PS_ERROR_SERVICE_NOT_FOUND:
ret = STMF_ERROR_SERVICE_NOT_FOUND;
break;
case STMF_PS_ERROR_VERSION_MISMATCH:
ret = STMF_ERROR_SERVICE_DATA_VERSION;
break;
default:
ret = STMF_STATUS_ERROR;
break;
}
if (ret != STMF_STATUS_SUCCESS) {
goto out;
}
for (j = 0; j < viewEntryList->cnt; j++) {
ret = addViewEntryIoctl(fd, &guidList->guid[i],
&viewEntryList->ve[j]);
if (ret != STMF_STATUS_SUCCESS) {
goto out;
}
}
}
ret = psGetProviderDataList(&providerList);
switch (ret) {
case STMF_PS_SUCCESS:
ret = STMF_STATUS_SUCCESS;
break;
case STMF_PS_ERROR_NOT_FOUND:
ret = STMF_ERROR_NOT_FOUND;
break;
case STMF_PS_ERROR_BUSY:
ret = STMF_ERROR_BUSY;
break;
case STMF_PS_ERROR_SERVICE_NOT_FOUND:
ret = STMF_ERROR_SERVICE_NOT_FOUND;
break;
case STMF_PS_ERROR_VERSION_MISMATCH:
ret = STMF_ERROR_SERVICE_DATA_VERSION;
break;
default:
ret = STMF_STATUS_ERROR;
break;
}
if (ret != STMF_STATUS_SUCCESS) {
goto out;
}
for (i = 0; i < providerList->cnt; i++) {
providerType = providerList->provider[i].providerType;
ret = psGetProviderData(providerList->provider[i].name,
&nvl, providerType, NULL);
switch (ret) {
case STMF_PS_SUCCESS:
ret = STMF_STATUS_SUCCESS;
break;
case STMF_PS_ERROR_NOT_FOUND:
ret = STMF_ERROR_NOT_FOUND;
break;
case STMF_PS_ERROR_BUSY:
ret = STMF_ERROR_BUSY;
break;
case STMF_PS_ERROR_SERVICE_NOT_FOUND:
ret = STMF_ERROR_SERVICE_NOT_FOUND;
break;
case STMF_PS_ERROR_VERSION_MISMATCH:
ret = STMF_ERROR_SERVICE_DATA_VERSION;
break;
default:
ret = STMF_STATUS_ERROR;
break;
}
if (ret != STMF_STATUS_SUCCESS) {
goto out;
}
ret = setProviderData(fd, providerList->provider[i].name, nvl,
providerType, NULL);
switch (ret) {
case STMF_PS_SUCCESS:
ret = STMF_STATUS_SUCCESS;
break;
case STMF_PS_ERROR_NOT_FOUND:
ret = STMF_ERROR_NOT_FOUND;
break;
case STMF_PS_ERROR_BUSY:
ret = STMF_ERROR_BUSY;
break;
case STMF_PS_ERROR_SERVICE_NOT_FOUND:
ret = STMF_ERROR_SERVICE_NOT_FOUND;
break;
case STMF_PS_ERROR_VERSION_MISMATCH:
ret = STMF_ERROR_SERVICE_DATA_VERSION;
break;
default:
ret = STMF_STATUS_ERROR;
break;
}
if (ret != STMF_STATUS_SUCCESS) {
goto out;
}
nvlist_free(nvl);
nvl = NULL;
}
out:
if (groupList != NULL) {
free(groupList);
}
if (guidList != NULL) {
free(guidList);
}
if (viewEntryList != NULL) {
free(viewEntryList);
}
if (nvl != NULL) {
nvlist_free(nvl);
}
return (ret);
}
int
stmfGetAluaState(boolean_t *enabled, uint32_t *node)
{
int ret = STMF_STATUS_SUCCESS;
int fd;
stmf_iocdata_t stmfIoctl = {0};
stmf_alua_state_desc_t alua_state = {0};
int ioctlRet;
if (enabled == NULL || node == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
stmfIoctl.stmf_version = STMF_VERSION_1;
stmfIoctl.stmf_obuf_size = sizeof (alua_state);
stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&alua_state;
ioctlRet = ioctl(fd, STMF_IOCTL_GET_ALUA_STATE, &stmfIoctl);
(void) close(fd);
if (ioctlRet != 0) {
switch (errno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
default:
syslog(LOG_DEBUG,
"getStmfState:ioctl errno(%d)", errno);
ret = STMF_STATUS_ERROR;
break;
}
} else {
if (alua_state.alua_state == 1) {
*enabled = B_TRUE;
} else {
*enabled = B_FALSE;
}
*node = alua_state.alua_node;
}
return (ret);
}
int
stmfSetAluaState(boolean_t enabled, uint32_t node)
{
int ret = STMF_STATUS_SUCCESS;
int fd;
stmf_iocdata_t stmfIoctl = {0};
stmf_alua_state_desc_t alua_state = {0};
int ioctlRet;
if ((enabled != B_TRUE && enabled != B_FALSE) || (node > 1)) {
return (STMF_ERROR_INVALID_ARG);
}
if (enabled) {
alua_state.alua_state = 1;
}
alua_state.alua_node = node;
if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
stmfIoctl.stmf_version = STMF_VERSION_1;
stmfIoctl.stmf_ibuf_size = sizeof (alua_state);
stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&alua_state;
ioctlRet = ioctl(fd, STMF_IOCTL_SET_ALUA_STATE, &stmfIoctl);
(void) close(fd);
if (ioctlRet != 0) {
switch (errno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
default:
syslog(LOG_DEBUG,
"getStmfState:ioctl errno(%d)", errno);
ret = STMF_STATUS_ERROR;
break;
}
}
if (!enabled && ret == STMF_STATUS_SUCCESS) {
deleteNonActiveLus();
}
return (ret);
}
static void
deleteNonActiveLus()
{
int stmfRet;
int i;
stmfGuidList *luList;
luResource hdl = NULL;
char propVal[10];
size_t propValSize = sizeof (propVal);
stmfRet = stmfGetLogicalUnitList(&luList);
if (stmfRet != STMF_STATUS_SUCCESS) {
return;
}
for (i = 0; i < luList->cnt; i++) {
stmfRet = stmfGetLuResource(&luList->guid[i], &hdl);
if (stmfRet != STMF_STATUS_SUCCESS) {
goto err;
}
stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_ACCESS_STATE, propVal,
&propValSize);
if (stmfRet != STMF_STATUS_SUCCESS) {
goto err;
}
if (propVal[0] == '0') {
(void) stmfFreeLuResource(hdl);
hdl = NULL;
continue;
}
(void) stmfDeleteLu(&luList->guid[i]);
(void) stmfFreeLuResource(hdl);
hdl = NULL;
}
err:
stmfFreeMemory(luList);
(void) stmfFreeLuResource(hdl);
}
int
stmfLoadConfig(void)
{
int ret = STMF_STATUS_SUCCESS;
int fd;
stmf_state_desc_t stmfStateSet;
stmfState state;
if (iGetPersistMethod() == STMF_PERSIST_NONE) {
stmfStateSet.state = STMF_STATE_OFFLINE;
if ((ret = openStmf(OPEN_EXCL_STMF, &fd))
!= STMF_STATUS_SUCCESS) {
return (ret);
}
stmfStateSet.config_state = STMF_CONFIG_INIT_DONE;
goto done;
}
if (psCheckService() != STMF_STATUS_SUCCESS) {
return (STMF_ERROR_SERVICE_NOT_FOUND);
}
ret = stmfGetState(&state);
if (ret == STMF_STATUS_SUCCESS) {
if (state.operationalState != STMF_SERVICE_STATE_OFFLINE) {
return (STMF_ERROR_SERVICE_ONLINE);
}
} else {
return (STMF_STATUS_ERROR);
}
stmfStateSet.state = STMF_STATE_OFFLINE;
stmfStateSet.config_state = STMF_CONFIG_INIT;
if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE);
if (ret != STMF_STATUS_SUCCESS) {
goto done;
}
ret = loadStore(fd);
if (ret != 0) {
goto done;
}
stmfStateSet.state = STMF_STATE_OFFLINE;
stmfStateSet.config_state = STMF_CONFIG_INIT_DONE;
done:
if (ret == STMF_STATUS_SUCCESS) {
ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE);
}
(void) close(fd);
return (ret);
}
static int
getStmfState(stmf_state_desc_t *stmfState)
{
int ret = STMF_STATUS_SUCCESS;
int fd;
int ioctlRet;
stmf_iocdata_t stmfIoctl;
if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
bzero(&stmfIoctl, sizeof (stmfIoctl));
stmfIoctl.stmf_version = STMF_VERSION_1;
stmfIoctl.stmf_ibuf_size = sizeof (stmf_state_desc_t);
stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)stmfState;
stmfIoctl.stmf_obuf_size = sizeof (stmf_state_desc_t);
stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)stmfState;
ioctlRet = ioctl(fd, STMF_IOCTL_GET_STMF_STATE, &stmfIoctl);
(void) close(fd);
if (ioctlRet != 0) {
switch (errno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
default:
syslog(LOG_DEBUG,
"getStmfState:ioctl errno(%d)", errno);
ret = STMF_STATUS_ERROR;
break;
}
}
return (ret);
}
static int
setStmfState(int fd, stmf_state_desc_t *stmfState, int objectType)
{
int ret = STMF_STATUS_SUCCESS;
int ioctlRet;
int cmd;
stmf_iocdata_t stmfIoctl;
switch (objectType) {
case LOGICAL_UNIT_TYPE:
cmd = STMF_IOCTL_SET_LU_STATE;
break;
case TARGET_TYPE:
cmd = STMF_IOCTL_SET_TARGET_PORT_STATE;
break;
case STMF_SERVICE_TYPE:
cmd = STMF_IOCTL_SET_STMF_STATE;
break;
default:
ret = STMF_STATUS_ERROR;
goto done;
}
bzero(&stmfIoctl, sizeof (stmfIoctl));
stmfIoctl.stmf_version = STMF_VERSION_1;
stmfIoctl.stmf_ibuf_size = sizeof (stmf_state_desc_t);
stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)stmfState;
ioctlRet = ioctl(fd, cmd, &stmfIoctl);
if (ioctlRet != 0) {
switch (errno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
case ENOENT:
ret = STMF_ERROR_NOT_FOUND;
break;
default:
syslog(LOG_DEBUG,
"setStmfState:ioctl errno(%d)", errno);
ret = STMF_STATUS_ERROR;
break;
}
}
done:
return (ret);
}
int
stmfSetStmfProp(uint8_t propType, char *propVal)
{
int ret = STMF_STATUS_SUCCESS;
switch (propType) {
case STMF_DEFAULT_LU_STATE:
break;
case STMF_DEFAULT_TARGET_PORT_STATE:
break;
default:
return (STMF_ERROR_INVALID_ARG);
}
ret = psSetStmfProp(propType, propVal);
switch (ret) {
case STMF_PS_SUCCESS:
ret = STMF_STATUS_SUCCESS;
break;
case STMF_PS_ERROR_BUSY:
ret = STMF_ERROR_BUSY;
break;
default:
syslog(LOG_DEBUG,
"stmfSetStmfProp:psSetStmfProp:error(%d)",
ret);
ret = STMF_STATUS_ERROR;
break;
}
return (ret);
}
int
stmfGetStmfProp(uint8_t propType, char *propVal, size_t *propLen)
{
int ret = STMF_STATUS_SUCCESS;
char prop[MAXNAMELEN] = {0};
size_t reqLen;
if (propVal == NULL || propLen == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
switch (propType) {
case STMF_DEFAULT_LU_STATE:
break;
case STMF_DEFAULT_TARGET_PORT_STATE:
break;
default:
return (STMF_ERROR_INVALID_ARG);
}
ret = psGetStmfProp(propType, prop);
if ((reqLen = strlcpy(propVal, prop, *propLen)) >= *propLen) {
*propLen = reqLen + 1;
return (STMF_ERROR_INVALID_ARG);
}
switch (ret) {
case STMF_PS_SUCCESS:
ret = STMF_STATUS_SUCCESS;
break;
case STMF_PS_ERROR_BUSY:
ret = STMF_ERROR_BUSY;
break;
case STMF_PS_ERROR_NOT_FOUND:
ret = STMF_ERROR_NOT_FOUND;
break;
default:
syslog(LOG_DEBUG,
"stmfGetStmfProp:psGetStmfProp:error(%d)",
ret);
ret = STMF_STATUS_ERROR;
break;
}
return (ret);
}
static int
setStmfProp(stmf_set_props_t *stmf_set_props)
{
char propVal[MAXNAMELEN] = {0};
int ret;
if ((ret = psGetStmfProp(STMF_DEFAULT_LU_STATE, propVal)) ==
STMF_PS_SUCCESS) {
if (strncmp(propVal, "offline", strlen(propVal)) == 0) {
stmf_set_props->default_lu_state_value =
STMF_STATE_OFFLINE;
} else {
stmf_set_props->default_lu_state_value =
STMF_STATE_ONLINE;
}
} else {
syslog(LOG_DEBUG,
"DefaultLuState:psSetStmfProp:error(%d)", ret);
goto done;
}
if ((ret = psGetStmfProp(STMF_DEFAULT_TARGET_PORT_STATE, propVal)) ==
STMF_PS_SUCCESS) {
if (strncmp(propVal, "offline", strlen(propVal)) == 0) {
stmf_set_props->default_target_state_value =
STMF_STATE_OFFLINE;
} else {
stmf_set_props->default_target_state_value =
STMF_STATE_ONLINE;
}
} else {
syslog(LOG_DEBUG,
"DefaultTargetPortState:psSetStmfProp:error(%d)", ret);
goto done;
}
done:
switch (ret) {
case STMF_PS_SUCCESS:
ret = STMF_STATUS_SUCCESS;
break;
case STMF_PS_ERROR_NOT_FOUND:
ret = STMF_ERROR_NOT_FOUND;
break;
case STMF_PS_ERROR_BUSY:
ret = STMF_ERROR_BUSY;
break;
default:
ret = STMF_STATUS_ERROR;
break;
}
return (ret);
}
static int
loadStmfProp(int fd)
{
int ret = STMF_STATUS_SUCCESS;
int ioctlRet;
stmf_iocdata_t stmfIoctl = {0};
stmf_set_props_t *stmf_set_props = NULL;
stmf_set_props = (stmf_set_props_t *)
calloc(1, (sizeof (stmf_set_props_t)));
if (stmf_set_props == NULL) {
ret = STMF_ERROR_NOMEM;
goto done;
}
if ((ret = setStmfProp(stmf_set_props)) != STMF_STATUS_SUCCESS)
goto done;
stmfIoctl.stmf_version = STMF_VERSION_1;
stmfIoctl.stmf_ibuf_size = sizeof (stmf_set_props_t);
stmfIoctl.stmf_ibuf =
(uint64_t)(unsigned long)stmf_set_props;
ioctlRet = ioctl(fd, STMF_IOCTL_SET_STMF_PROPS,
&stmfIoctl);
if (ioctlRet != 0) {
switch (errno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
case ENOENT:
ret = STMF_ERROR_NOT_FOUND;
break;
default:
syslog(LOG_DEBUG,
"setDefaultStmfState:"
"ioctl errno(%d)", errno);
ret = STMF_STATUS_ERROR;
break;
}
}
done:
if (stmf_set_props != NULL) {
free(stmf_set_props);
}
return (ret);
}
int
stmfLoadStmfProps(void)
{
int ret = STMF_STATUS_SUCCESS;
int fd;
if ((ret = openStmf(OPEN_EXCL_STMF, &fd))
!= STMF_STATUS_SUCCESS) {
goto done;
}
ret = loadStmfProp(fd);
(void) close(fd);
done:
if (ret != STMF_STATUS_SUCCESS) {
syslog(LOG_DEBUG,
"stmfLoadStmfProps:Failed");
}
return (ret);
}
int
stmfOnline(void)
{
int ret;
int fd;
stmfState state;
stmf_state_desc_t iState;
ret = stmfGetState(&state);
if (ret == STMF_STATUS_SUCCESS) {
if (state.operationalState == STMF_SERVICE_STATE_ONLINE) {
return (STMF_ERROR_SERVICE_ONLINE);
}
} else {
return (STMF_STATUS_ERROR);
}
iState.state = STMF_STATE_ONLINE;
iState.config_state = STMF_CONFIG_NONE;
if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
ret = setStmfState(fd, &iState, STMF_SERVICE_TYPE);
(void) close(fd);
return (ret);
}
int
stmfOffline(void)
{
int ret;
int fd;
stmfState state;
stmf_state_desc_t iState;
ret = stmfGetState(&state);
if (ret == STMF_STATUS_SUCCESS) {
if (state.operationalState == STMF_SERVICE_STATE_OFFLINE) {
return (STMF_ERROR_SERVICE_OFFLINE);
}
} else {
return (STMF_STATUS_ERROR);
}
iState.state = STMF_STATE_OFFLINE;
iState.config_state = STMF_CONFIG_NONE;
if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
ret = setStmfState(fd, &iState, STMF_SERVICE_TYPE);
(void) close(fd);
return (ret);
}
int
stmfOfflineTarget(stmfDevid *devid)
{
stmf_state_desc_t targetState;
int ret = STMF_STATUS_SUCCESS;
int fd;
if (devid == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
bzero(&targetState, sizeof (targetState));
targetState.state = STMF_STATE_OFFLINE;
targetState.ident[IDENT_LENGTH_BYTE] = devid->identLength;
bcopy(&(devid->ident), &targetState.ident[IDENT_LENGTH_BYTE + 1],
devid->identLength);
if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
ret = setStmfState(fd, &targetState, TARGET_TYPE);
(void) close(fd);
return (ret);
}
int
stmfOfflineLogicalUnit(stmfGuid *lu)
{
stmf_state_desc_t luState;
int ret = STMF_STATUS_SUCCESS;
int fd;
if (lu == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
bzero(&luState, sizeof (luState));
luState.state = STMF_STATE_OFFLINE;
bcopy(lu, &luState.ident, sizeof (stmfGuid));
if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
ret = setStmfState(fd, &luState, LOGICAL_UNIT_TYPE);
(void) close(fd);
return (ret);
}
int
stmfOnlineTarget(stmfDevid *devid)
{
stmf_state_desc_t targetState;
int ret = STMF_STATUS_SUCCESS;
int fd;
if (devid == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
bzero(&targetState, sizeof (targetState));
targetState.state = STMF_STATE_ONLINE;
targetState.ident[IDENT_LENGTH_BYTE] = devid->identLength;
bcopy(&(devid->ident), &targetState.ident[IDENT_LENGTH_BYTE + 1],
devid->identLength);
if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
ret = setStmfState(fd, &targetState, TARGET_TYPE);
(void) close(fd);
return (ret);
}
int
stmfOnlineLogicalUnit(stmfGuid *lu)
{
stmf_state_desc_t luState;
int ret = STMF_STATUS_SUCCESS;
int fd;
if (lu == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
bzero(&luState, sizeof (luState));
luState.state = STMF_STATE_ONLINE;
bcopy(lu, &luState.ident, sizeof (stmfGuid));
if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
ret = setStmfState(fd, &luState, LOGICAL_UNIT_TYPE);
(void) close(fd);
return (ret);
}
int
stmfRemoveFromHostGroup(stmfGroupName *hostGroupName, stmfDevid *hostName)
{
int ret;
int fd;
if (hostGroupName == NULL ||
(strnlen((char *)hostGroupName, sizeof (stmfGroupName))
== sizeof (stmfGroupName)) || hostName == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
ret = initializeConfig();
if (ret != STMF_STATUS_SUCCESS) {
return (ret);
}
if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
if ((ret = groupMemberIoctl(fd, STMF_IOCTL_REMOVE_HG_ENTRY,
hostGroupName, hostName)) != STMF_STATUS_SUCCESS) {
goto done;
}
if (iGetPersistMethod() == STMF_PERSIST_NONE) {
goto done;
}
ret = psRemoveHostGroupMember((char *)hostGroupName,
(char *)hostName->ident);
switch (ret) {
case STMF_PS_SUCCESS:
ret = STMF_STATUS_SUCCESS;
break;
case STMF_PS_ERROR_MEMBER_NOT_FOUND:
ret = STMF_ERROR_MEMBER_NOT_FOUND;
break;
case STMF_PS_ERROR_GROUP_NOT_FOUND:
ret = STMF_ERROR_GROUP_NOT_FOUND;
break;
case STMF_PS_ERROR_BUSY:
ret = STMF_ERROR_BUSY;
break;
case STMF_PS_ERROR_SERVICE_NOT_FOUND:
ret = STMF_ERROR_SERVICE_NOT_FOUND;
break;
case STMF_PS_ERROR_VERSION_MISMATCH:
ret = STMF_ERROR_SERVICE_DATA_VERSION;
break;
default:
syslog(LOG_DEBUG,
"stmfRemoveFromHostGroup"
"psRemoveHostGroupMember:error(%d)", ret);
ret = STMF_STATUS_ERROR;
break;
}
done:
(void) close(fd);
return (ret);
}
int
stmfRemoveFromTargetGroup(stmfGroupName *targetGroupName, stmfDevid *targetName)
{
int ret;
int fd;
if (targetGroupName == NULL ||
(strnlen((char *)targetGroupName, sizeof (stmfGroupName))
== sizeof (stmfGroupName)) || targetName == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
ret = initializeConfig();
if (ret != STMF_STATUS_SUCCESS) {
return (ret);
}
if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
if ((ret = groupMemberIoctl(fd, STMF_IOCTL_REMOVE_TG_ENTRY,
targetGroupName, targetName)) != STMF_STATUS_SUCCESS) {
goto done;
}
if (iGetPersistMethod() == STMF_PERSIST_NONE) {
goto done;
}
ret = psRemoveTargetGroupMember((char *)targetGroupName,
(char *)targetName->ident);
switch (ret) {
case STMF_PS_SUCCESS:
ret = STMF_STATUS_SUCCESS;
break;
case STMF_PS_ERROR_MEMBER_NOT_FOUND:
ret = STMF_ERROR_MEMBER_NOT_FOUND;
break;
case STMF_PS_ERROR_GROUP_NOT_FOUND:
ret = STMF_ERROR_GROUP_NOT_FOUND;
break;
case STMF_PS_ERROR_BUSY:
ret = STMF_ERROR_BUSY;
break;
case STMF_PS_ERROR_SERVICE_NOT_FOUND:
ret = STMF_ERROR_SERVICE_NOT_FOUND;
break;
case STMF_PS_ERROR_VERSION_MISMATCH:
ret = STMF_ERROR_SERVICE_DATA_VERSION;
break;
default:
syslog(LOG_DEBUG,
"stmfRemoveFromTargetGroup"
"psRemoveTargetGroupMember:error(%d)", ret);
ret = STMF_STATUS_ERROR;
break;
}
done:
(void) close(fd);
return (ret);
}
int
stmfRemoveViewEntry(stmfGuid *lu, uint32_t viewEntryIndex)
{
int ret = STMF_STATUS_SUCCESS;
int fd;
int ioctlRet;
stmf_iocdata_t stmfIoctl;
stmf_view_op_entry_t ioctlViewEntry;
if (lu == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
ret = initializeConfig();
if (ret != STMF_STATUS_SUCCESS) {
return (ret);
}
if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
bzero(&ioctlViewEntry, sizeof (ioctlViewEntry));
ioctlViewEntry.ve_ndx_valid = B_TRUE;
ioctlViewEntry.ve_ndx = viewEntryIndex;
bcopy(lu, &ioctlViewEntry.ve_guid, sizeof (stmfGuid));
bzero(&stmfIoctl, sizeof (stmfIoctl));
stmfIoctl.stmf_version = STMF_VERSION_1;
stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry);
stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry;
ioctlRet = ioctl(fd, STMF_IOCTL_REMOVE_VIEW_ENTRY, &stmfIoctl);
if (ioctlRet != 0) {
switch (errno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
ret = STMF_ERROR_PERM;
break;
case EACCES:
switch (stmfIoctl.stmf_error) {
case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
ret = STMF_ERROR_CONFIG_NONE;
break;
default:
ret = STMF_ERROR_PERM;
break;
}
break;
case ENODEV:
case ENOENT:
ret = STMF_ERROR_NOT_FOUND;
break;
default:
syslog(LOG_DEBUG,
"stmfRemoveViewEntry:ioctl errno(%d)",
errno);
ret = STMF_STATUS_ERROR;
break;
}
goto done;
}
if (iGetPersistMethod() == STMF_PERSIST_NONE) {
goto done;
}
ret = psRemoveViewEntry(lu, viewEntryIndex);
switch (ret) {
case STMF_PS_SUCCESS:
ret = STMF_STATUS_SUCCESS;
break;
case STMF_PS_ERROR_NOT_FOUND:
ret = STMF_ERROR_NOT_FOUND;
break;
case STMF_PS_ERROR_BUSY:
ret = STMF_ERROR_BUSY;
break;
case STMF_PS_ERROR_SERVICE_NOT_FOUND:
ret = STMF_ERROR_SERVICE_NOT_FOUND;
break;
case STMF_PS_ERROR_VERSION_MISMATCH:
ret = STMF_ERROR_SERVICE_DATA_VERSION;
break;
default:
syslog(LOG_DEBUG,
"stmfRemoveViewEntry" "psRemoveViewEntry:error(%d)",
ret);
ret = STMF_STATUS_ERROR;
break;
}
done:
(void) close(fd);
return (ret);
}
int
stmfSetProviderData(char *providerName, nvlist_t *nvl, int providerType)
{
return (stmfSetProviderDataProt(providerName, nvl, providerType,
NULL));
}
int
stmfSetProviderDataProt(char *providerName, nvlist_t *nvl, int providerType,
uint64_t *setToken)
{
int ret;
int fd;
if (providerName == NULL || nvl == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
if (providerType != STMF_LU_PROVIDER_TYPE &&
providerType != STMF_PORT_PROVIDER_TYPE) {
return (STMF_ERROR_INVALID_ARG);
}
ret = initializeConfig();
if (ret != STMF_STATUS_SUCCESS) {
return (ret);
}
if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
ret = setProviderData(fd, providerName, nvl, providerType, setToken);
(void) close(fd);
if (ret != STMF_STATUS_SUCCESS) {
goto done;
}
if (iGetPersistMethod() == STMF_PERSIST_NONE) {
goto done;
}
ret = psSetProviderData(providerName, nvl, providerType, NULL);
switch (ret) {
case STMF_PS_SUCCESS:
ret = STMF_STATUS_SUCCESS;
break;
case STMF_PS_ERROR_EXISTS:
ret = STMF_ERROR_EXISTS;
break;
case STMF_PS_ERROR_BUSY:
ret = STMF_ERROR_BUSY;
break;
case STMF_PS_ERROR_SERVICE_NOT_FOUND:
ret = STMF_ERROR_SERVICE_NOT_FOUND;
break;
case STMF_PS_ERROR_VERSION_MISMATCH:
ret = STMF_ERROR_SERVICE_DATA_VERSION;
break;
case STMF_PS_ERROR_PROV_DATA_STALE:
ret = STMF_ERROR_PROV_DATA_STALE;
break;
default:
syslog(LOG_DEBUG,
"stmfSetProviderData"
"psSetProviderData:error(%d)", ret);
ret = STMF_STATUS_ERROR;
break;
}
done:
return (ret);
}
int
getProviderData(char *providerName, nvlist_t **nvl, int providerType,
uint64_t *setToken)
{
int ret = STMF_STATUS_SUCCESS;
int fd;
int ioctlRet;
size_t nvlistSize = ALLOC_PP_DATA_SIZE;
int retryCnt = 0;
int retryCntMax = MAX_PROVIDER_RETRY;
stmf_ppioctl_data_t ppi = {0}, *ppi_out = NULL;
boolean_t retry = B_TRUE;
stmf_iocdata_t stmfIoctl;
if (providerName == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
if (strlcpy(ppi.ppi_name, providerName,
sizeof (ppi.ppi_name)) >=
sizeof (ppi.ppi_name)) {
ret = STMF_ERROR_INVALID_ARG;
goto done;
}
switch (providerType) {
case STMF_LU_PROVIDER_TYPE:
ppi.ppi_lu_provider = 1;
break;
case STMF_PORT_PROVIDER_TYPE:
ppi.ppi_port_provider = 1;
break;
default:
ret = STMF_ERROR_INVALID_ARG;
goto done;
}
do {
ppi_out = (stmf_ppioctl_data_t *)calloc(1, nvlistSize +
sizeof (stmf_ppioctl_data_t));
if (ppi_out == NULL) {
ret = STMF_ERROR_NOMEM;
goto done;
}
ppi.ppi_data_size = nvlistSize;
bzero(&stmfIoctl, sizeof (stmfIoctl));
stmfIoctl.stmf_version = STMF_VERSION_1;
stmfIoctl.stmf_ibuf_size = sizeof (stmf_ppioctl_data_t);
stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ppi;
stmfIoctl.stmf_obuf_size = sizeof (stmf_ppioctl_data_t) +
nvlistSize;
stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)ppi_out;
ioctlRet = ioctl(fd, STMF_IOCTL_GET_PP_DATA, &stmfIoctl);
if (ioctlRet != 0) {
switch (errno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
case EINVAL:
if (stmfIoctl.stmf_error ==
STMF_IOCERR_INSUFFICIENT_BUF) {
nvlistSize =
ppi_out->ppi_data_size;
free(ppi_out);
ppi_out = NULL;
if (retryCnt++ > retryCntMax) {
retry = B_FALSE;
ret = STMF_ERROR_BUSY;
} else {
ret =
STMF_STATUS_SUCCESS;
}
} else {
syslog(LOG_DEBUG,
"getProviderData:ioctl"
"unable to retrieve "
"nvlist");
ret = STMF_STATUS_ERROR;
}
break;
case ENOENT:
ret = STMF_ERROR_NOT_FOUND;
break;
default:
syslog(LOG_DEBUG,
"getProviderData:ioctl errno(%d)",
errno);
ret = STMF_STATUS_ERROR;
break;
}
if (ret != STMF_STATUS_SUCCESS)
goto done;
}
} while (retry && stmfIoctl.stmf_error == STMF_IOCERR_INSUFFICIENT_BUF);
if ((ret = nvlist_unpack((char *)ppi_out->ppi_data,
ppi_out->ppi_data_size, nvl, 0)) != 0) {
ret = STMF_STATUS_ERROR;
goto done;
}
if (setToken) {
*setToken = ppi_out->ppi_token;
}
done:
free(ppi_out);
(void) close(fd);
return (ret);
}
static int
setProviderData(int fd, char *providerName, nvlist_t *nvl, int providerType,
uint64_t *setToken)
{
int ret = STMF_STATUS_SUCCESS;
int ioctlRet;
size_t nvlistEncodedSize;
stmf_ppioctl_data_t *ppi = NULL;
uint64_t outToken;
char *allocatedNvBuffer;
stmf_iocdata_t stmfIoctl;
if (providerName == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
if (nvlist_size(nvl, &nvlistEncodedSize, NV_ENCODE_XDR) != 0) {
return (STMF_STATUS_ERROR);
}
ppi = (stmf_ppioctl_data_t *)calloc(1, nvlistEncodedSize +
sizeof (stmf_ppioctl_data_t));
if (ppi == NULL) {
return (STMF_ERROR_NOMEM);
}
if (setToken) {
ppi->ppi_token_valid = 1;
ppi->ppi_token = *setToken;
}
allocatedNvBuffer = (char *)&ppi->ppi_data;
if (nvlist_pack(nvl, &allocatedNvBuffer, &nvlistEncodedSize,
NV_ENCODE_XDR, 0) != 0) {
return (STMF_STATUS_ERROR);
}
(void) strncpy(ppi->ppi_name, providerName, sizeof (ppi->ppi_name));
switch (providerType) {
case STMF_LU_PROVIDER_TYPE:
ppi->ppi_lu_provider = 1;
break;
case STMF_PORT_PROVIDER_TYPE:
ppi->ppi_port_provider = 1;
break;
default:
return (STMF_ERROR_INVALID_ARG);
}
ppi->ppi_data_size = nvlistEncodedSize;
bzero(&stmfIoctl, sizeof (stmfIoctl));
stmfIoctl.stmf_version = STMF_VERSION_1;
stmfIoctl.stmf_ibuf_size = nvlistEncodedSize +
sizeof (stmf_ppioctl_data_t) - 8;
stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)ppi;
stmfIoctl.stmf_obuf_size = sizeof (uint64_t);
stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&outToken;
ioctlRet = ioctl(fd, STMF_IOCTL_LOAD_PP_DATA, &stmfIoctl);
if (ioctlRet != 0) {
switch (errno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
case EINVAL:
if (stmfIoctl.stmf_error ==
STMF_IOCERR_PPD_UPDATED) {
ret = STMF_ERROR_PROV_DATA_STALE;
} else {
ret = STMF_STATUS_ERROR;
}
break;
default:
syslog(LOG_DEBUG,
"setProviderData:ioctl errno(%d)", errno);
ret = STMF_STATUS_ERROR;
break;
}
if (ret != STMF_STATUS_SUCCESS)
goto done;
}
if (setToken) {
*setToken = outToken;
}
done:
free(ppi);
return (ret);
}
int
stmfSetPersistMethod(uint8_t persistType, boolean_t serviceSet)
{
int ret = STMF_STATUS_SUCCESS;
int oldPersist;
(void) pthread_mutex_lock(&persistenceTypeLock);
oldPersist = iPersistType;
if (persistType == STMF_PERSIST_NONE ||
persistType == STMF_PERSIST_SMF) {
iLibSetPersist = B_TRUE;
iPersistType = persistType;
} else {
(void) pthread_mutex_unlock(&persistenceTypeLock);
return (STMF_ERROR_INVALID_ARG);
}
if (serviceSet == B_TRUE) {
ret = psSetServicePersist(persistType);
if (ret != STMF_PS_SUCCESS) {
ret = STMF_ERROR_PERSIST_TYPE;
iPersistType = oldPersist;
}
}
(void) pthread_mutex_unlock(&persistenceTypeLock);
return (ret);
}
static uint8_t
iGetPersistMethod()
{
uint8_t persistType = 0;
(void) pthread_mutex_lock(&persistenceTypeLock);
if (iLibSetPersist) {
persistType = iPersistType;
} else {
int ret;
ret = psGetServicePersist(&persistType);
if (ret != STMF_PS_SUCCESS) {
persistType = STMF_DEFAULT_PERSIST;
}
}
(void) pthread_mutex_unlock(&persistenceTypeLock);
return (persistType);
}
int
stmfGetPersistMethod(uint8_t *persistType, boolean_t serviceState)
{
int ret = STMF_STATUS_SUCCESS;
if (persistType == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
if (serviceState) {
ret = psGetServicePersist(persistType);
if (ret != STMF_PS_SUCCESS) {
ret = STMF_ERROR_PERSIST_TYPE;
}
} else {
(void) pthread_mutex_lock(&persistenceTypeLock);
if (iLibSetPersist) {
*persistType = iPersistType;
} else {
*persistType = STMF_DEFAULT_PERSIST;
}
(void) pthread_mutex_unlock(&persistenceTypeLock);
}
return (ret);
}
int
stmfPostProxyMsg(int hdl, void *buf, uint32_t buflen)
{
int ret = STMF_STATUS_SUCCESS;
int ioctlRet;
pppt_iocdata_t ppptIoctl = {0};
if (buf == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
ppptIoctl.pppt_version = PPPT_VERSION_1;
ppptIoctl.pppt_buf_size = buflen;
ppptIoctl.pppt_buf = (uint64_t)(unsigned long)buf;
ioctlRet = ioctl(hdl, PPPT_MESSAGE, &ppptIoctl);
if (ioctlRet != 0) {
switch (errno) {
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
default:
ret = STMF_ERROR_POST_MSG_FAILED;
break;
}
}
return (ret);
}
int
stmfInitProxyDoor(int *hdl, int door)
{
int ret = STMF_STATUS_SUCCESS;
int ioctlRet;
int fd;
pppt_iocdata_t ppptIoctl = {0};
if (hdl == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
if ((ret = openPppt(OPEN_PPPT, &fd)) != STMF_STATUS_SUCCESS) {
return (ret);
}
ppptIoctl.pppt_version = PPPT_VERSION_1;
ppptIoctl.pppt_door_fd = (uint32_t)door;
ioctlRet = ioctl(fd, PPPT_INSTALL_DOOR, &ppptIoctl);
if (ioctlRet != 0) {
switch (errno) {
case EPERM:
case EACCES:
ret = STMF_ERROR_PERM;
break;
case EINVAL:
ret = STMF_ERROR_INVALID_ARG;
break;
case EBUSY:
ret = STMF_ERROR_DOOR_INSTALLED;
break;
default:
ret = STMF_STATUS_ERROR;
break;
}
}
*hdl = fd;
return (ret);
}
void
stmfDestroyProxyDoor(int hdl)
{
(void) close(hdl);
}
static int
validateLunNumIoctl(int fd, stmfViewEntry *viewEntry)
{
int ret = STMF_STATUS_SUCCESS;
int ioctlRet;
stmf_iocdata_t stmfIoctl;
stmf_view_op_entry_t ioctlViewEntry;
bzero(&ioctlViewEntry, sizeof (ioctlViewEntry));
ioctlViewEntry.ve_lu_number_valid = viewEntry->luNbrValid;
ioctlViewEntry.ve_all_hosts = viewEntry->allHosts;
ioctlViewEntry.ve_all_targets = viewEntry->allTargets;
if (viewEntry->allHosts == B_FALSE) {
bcopy(viewEntry->hostGroup, &ioctlViewEntry.ve_host_group.name,
sizeof (stmfGroupName));
ioctlViewEntry.ve_host_group.name_size =
strlen((char *)viewEntry->hostGroup);
}
if (viewEntry->allTargets == B_FALSE) {
bcopy(viewEntry->targetGroup,
&ioctlViewEntry.ve_target_group.name,
sizeof (stmfGroupName));
ioctlViewEntry.ve_target_group.name_size =
strlen((char *)viewEntry->targetGroup);
}
if (viewEntry->luNbrValid) {
bcopy(viewEntry->luNbr, &ioctlViewEntry.ve_lu_nbr,
sizeof (ioctlViewEntry.ve_lu_nbr));
}
bzero(&stmfIoctl, sizeof (stmfIoctl));
stmfIoctl.stmf_version = STMF_VERSION_1;
stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry);
stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry;
stmfIoctl.stmf_obuf_size = sizeof (ioctlViewEntry);
stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&ioctlViewEntry;
ioctlRet = ioctl(fd, STMF_IOCTL_VALIDATE_VIEW, &stmfIoctl);
if (!viewEntry->luNbrValid) {
bcopy(ioctlViewEntry.ve_lu_nbr, viewEntry->luNbr,
sizeof (ioctlViewEntry.ve_lu_nbr));
}
if (ioctlRet != 0) {
switch (errno) {
case EBUSY:
ret = STMF_ERROR_BUSY;
break;
case EPERM:
ret = STMF_ERROR_PERM;
break;
case EACCES:
switch (stmfIoctl.stmf_error) {
case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
ret = STMF_ERROR_CONFIG_NONE;
break;
default:
ret = STMF_ERROR_PERM;
break;
}
break;
default:
switch (stmfIoctl.stmf_error) {
case STMF_IOCERR_LU_NUMBER_IN_USE:
ret = STMF_ERROR_LUN_IN_USE;
break;
case STMF_IOCERR_VIEW_ENTRY_CONFLICT:
ret = STMF_ERROR_VE_CONFLICT;
break;
case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
ret = STMF_ERROR_CONFIG_NONE;
break;
case STMF_IOCERR_INVALID_HG:
ret = STMF_ERROR_INVALID_HG;
break;
case STMF_IOCERR_INVALID_TG:
ret = STMF_ERROR_INVALID_TG;
break;
default:
syslog(LOG_DEBUG,
"addViewEntryIoctl"
":error(%d)",
stmfIoctl.stmf_error);
ret = STMF_STATUS_ERROR;
break;
}
break;
}
}
return (ret);
}
int
stmfValidateView(stmfViewEntry *viewEntry)
{
int ret;
int fd;
stmfViewEntry iViewEntry;
if (viewEntry == NULL) {
return (STMF_ERROR_INVALID_ARG);
}
bzero(&iViewEntry, sizeof (iViewEntry));
if (!viewEntry->allHosts) {
bcopy(viewEntry->hostGroup, iViewEntry.hostGroup,
sizeof (iViewEntry.hostGroup));
} else {
iViewEntry.allHosts = B_TRUE;
}
if (!viewEntry->allTargets) {
bcopy(viewEntry->targetGroup, iViewEntry.targetGroup,
sizeof (iViewEntry.targetGroup));
} else {
iViewEntry.allTargets = B_TRUE;
}
if (viewEntry->luNbrValid) {
iViewEntry.luNbrValid = B_TRUE;
bcopy(viewEntry->luNbr, iViewEntry.luNbr,
sizeof (iViewEntry.luNbr));
}
viewEntry->veIndexValid = B_FALSE;
if (psCheckService() != STMF_STATUS_SUCCESS) {
return (STMF_ERROR_SERVICE_NOT_FOUND);
}
ret = initializeConfig();
if (ret != STMF_STATUS_SUCCESS) {
return (ret);
}
if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
return (ret);
ret = validateLunNumIoctl(fd, &iViewEntry);
(void) close(fd);
if (!viewEntry->luNbrValid) {
bcopy(iViewEntry.luNbr, viewEntry->luNbr,
sizeof (iViewEntry.luNbr));
}
return (ret);
}