/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <string.h>
#include <syslog.h>
#include <errno.h>
#include <unistd.h>
#include <stropts.h>
#include <libdevinfo.h>
#include "mp_utils.h"
typedef struct walk_devlink {
char *path;
size_t len;
char **linkpp;
} walk_devlink_t;
static int
get_devlink(di_devlink_t devlink, void *arg) {
walk_devlink_t *warg = (walk_devlink_t *)arg;
log(LOG_INFO, "get_devlink()", " - enter");
*(warg->linkpp) = strdup(di_devlink_path(devlink));
log(LOG_INFO, "get_devlink()", " - exit");
return (DI_WALK_TERMINATE);
}
char
*getDeviceFileName(MP_UINT64 objectSequenceNumber)
{
char *deviceFileName = NULL;
di_node_t root_node = DI_NODE_NIL;
di_node_t cur_node = DI_NODE_NIL;
int instNum;
int majorNum;
MP_UINT64 osn;
char *pathName = NULL;
char *minorName = "c,raw";
char *devLink = NULL;
char fullName[512];
walk_devlink_t warg;
di_devlink_handle_t dlHandle = NULL;
int diStatus = 0;
log(LOG_INFO, "getDeviceFileName()", " - enter");
log(LOG_INFO, "getDeviceFileName()",
" - objectSequenceNumber: %llx",
objectSequenceNumber);
root_node = di_init("/", DINFOCACHE);
if (DI_NODE_NIL == root_node) {
log(LOG_INFO, "MP_GetMultipathLusPlugin()",
" - $ERROR, di_init() failed");
return (NULL);
}
cur_node = di_drv_first_node("scsi_vhci", root_node);
if (DI_NODE_NIL == cur_node) {
log(LOG_INFO, "getDeviceFileName()",
" - $ERROR, di_drv_first_node() failed");
di_fini(root_node);
return (NULL);
}
cur_node = di_child_node(cur_node);
while (DI_NODE_NIL != cur_node) {
instNum = di_instance(cur_node);
majorNum = di_driver_major(cur_node);
osn = 0;
osn = MP_STORE_INST_TO_ID(instNum, osn);
osn = MP_STORE_MAJOR_TO_ID(majorNum, osn);
if (osn == objectSequenceNumber) {
log(LOG_INFO, "getDeviceFileName()",
" - found node.");
break;
}
cur_node = di_sibling_node(cur_node);
}
if (DI_NODE_NIL != cur_node) {
dlHandle = di_devlink_init(NULL, 0);
if (NULL == dlHandle) {
log(LOG_INFO, "getDeviceFileName()",
" - $ERROR, di_devlink_init() failed.");
di_fini(root_node);
return (NULL);
}
pathName = di_devfs_path(cur_node);
(void) snprintf(fullName, 511, "%s:%s", pathName, minorName);
log(LOG_INFO, "getDeviceFileName()",
" - fullName: {%s]", fullName);
(void) memset(&warg, 0, sizeof (walk_devlink_t));
devLink = NULL;
warg.linkpp = &devLink;
diStatus = di_devlink_walk(dlHandle,
NULL,
fullName,
DI_PRIMARY_LINK,
(void *)&warg,
get_devlink);
if (diStatus != 0) {
log(LOG_INFO, "getDeviceFileName()",
"diStatus: %d", diStatus);
if (diStatus < 0) {
diStatus = errno;
}
log(LOG_INFO, "getDeviceFileName()",
"diStatus: %d", diStatus);
log(LOG_INFO, "getDeviceFileName()",
"strerror(diStatus): %s", strerror(diStatus));
}
if (NULL != devLink) {
deviceFileName =
(char *)calloc(1, strlen(devLink) + 1);
(void) strncpy(deviceFileName, devLink,
strlen(devLink));
} else {
log(LOG_INFO, "getDeviceFileName()",
" - $ERROR, devLink is NULL.");
deviceFileName =
(char *)calloc(1, 256);
(void) strncpy(deviceFileName, pathName, 255);
}
di_devfs_path_free(pathName);
(void) di_devlink_fini(&dlHandle);
}
di_fini(root_node);
free(devLink);
log(LOG_INFO, "getDeviceFileName()", " - exit");
return (deviceFileName);
}
MP_STATUS
MP_GetMPLogicalUnitProperties(MP_OID oid,
MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES *pProps)
{
mp_iocdata_t mp_ioctl;
mp_logical_unit_prop_t luInfo;
MP_OID overridePathOID;
int ioctlStatus = 0;
int vendorLength = 0;
int productLength = 0;
int revisionLength = 0;
char *deviceFileName = NULL;
MP_STATUS mpStatus = MP_STATUS_SUCCESS;
log(LOG_INFO, "MP_GetMPLogicalUnitProperties()", " - enter");
log(LOG_INFO, "MP_GetMPLogicalUnitProperties()",
"oid.objectSequenceNumber = %llx",
oid.objectSequenceNumber);
if (g_scsi_vhci_fd < 0) {
log(LOG_INFO, "MP_GetMPLogicalUnitProperties()",
"invalid driver file handle");
log(LOG_INFO, "MP_GetMPLogicalUnitProperties()",
" - error exit");
return (MP_STATUS_FAILED);
}
(void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
(void) memset(&luInfo, 0, sizeof (mp_logical_unit_prop_t));
mp_ioctl.mp_cmd = MP_GET_LU_PROP;
mp_ioctl.mp_ibuf = (caddr_t)&oid.objectSequenceNumber;
mp_ioctl.mp_ilen = sizeof (oid.objectSequenceNumber);
mp_ioctl.mp_obuf = (caddr_t)&luInfo;
mp_ioctl.mp_olen = sizeof (mp_logical_unit_prop_t);
mp_ioctl.mp_xfer = MP_XFER_READ;
ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
log(LOG_INFO, "MP_GetMPLogicalUnitProperties()",
" IOCTL call returned: %d", ioctlStatus);
if (ioctlStatus < 0) {
ioctlStatus = errno;
}
if (ioctlStatus != 0) {
log(LOG_INFO, "MP_GetMPLogicalUnitProperties()",
"IOCTL call failed. IOCTL error is: %d",
ioctlStatus);
log(LOG_INFO, "MP_GetMPLogicalUnitProperties()",
"IOCTL call failed. IOCTL error is: %s",
strerror(ioctlStatus));
log(LOG_INFO, "MP_GetMPLogicalUnitProperties()",
"IOCTL call failed. mp_ioctl.mp_errno: %x",
mp_ioctl.mp_errno);
if (ENOTSUP == ioctlStatus) {
mpStatus = MP_STATUS_UNSUPPORTED;
} else if (0 == mp_ioctl.mp_errno) {
mpStatus = MP_STATUS_FAILED;
} else {
mpStatus = getStatus4ErrorCode(mp_ioctl.mp_errno);
}
log(LOG_INFO, "MP_GetMPLogicalUnitProperties()",
" - error exit");
return (mpStatus);
}
(void) memset(pProps, 0, sizeof (MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES));
pProps->asymmetric = luInfo.asymmetric;
pProps->autoFailbackEnabled = luInfo.autoFailbackEnabled;
pProps->autoProbingEnabled = luInfo.autoProbingEnabled;
pProps->currentFailbackPollingRate = luInfo.currentFailBackPollingRate;
pProps->currentLoadBalanceType = luInfo.currentLoadBalanceType;
pProps->currentProbingPollingRate = luInfo.currentProbingPollingRate;
deviceFileName = getDeviceFileName(oid.objectSequenceNumber);
if (NULL != deviceFileName) {
log(LOG_INFO, "MP_GetMPLogicalUnitProperties()",
"deviceFileName: %s",
deviceFileName);
(void) strncpy(pProps->deviceFileName,
deviceFileName,
sizeof (pProps->deviceFileName) - 1);
free(deviceFileName);
}
pProps->failbackPollingRateMax = luInfo.failbackPollingRateMax;
pProps->logicalUnitGroupID = luInfo.luGroupID;
(void) strncpy(pProps->name, luInfo.name, sizeof (pProps->name) - 1);
pProps->nameType = luInfo.nameType;
overridePathOID.objectSequenceNumber = luInfo.overridePathID;
overridePathOID.objectType = MP_OBJECT_TYPE_PATH_LU;
overridePathOID.ownerId = g_pluginOwnerID;
(void) memcpy(&pProps->overridePath, &overridePathOID, sizeof (MP_OID));
pProps->probingPollingRateMax = luInfo.probingPollingRateMax;
vendorLength = sizeof (pProps->vendor);
productLength = sizeof (pProps->product);
revisionLength = sizeof (pProps->revision);
(void) strncpy(pProps->vendor,
luInfo.prodInfo.vendor,
vendorLength);
(void) strncpy(pProps->product,
luInfo.prodInfo.product,
productLength);
(void) strncpy(pProps->revision,
luInfo.prodInfo.revision,
revisionLength);
log(LOG_INFO, "MP_GetMPLogicalUnitProperties()", " - exit");
return (MP_STATUS_SUCCESS);
}