/* * 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 #include #include #include #include #include #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); }