1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 #include <string.h> 26 #include <syslog.h> 27 #include <errno.h> 28 #include <unistd.h> 29 #include <stropts.h> 30 #include <libdevinfo.h> 31 32 #include "mp_utils.h" 33 34 35 static int getOidList(di_node_t root_node, 36 MP_OID_LIST *pOidList, 37 char *pProductID, 38 char *pVendorID) 39 { 40 int numNodes = 0; 41 int pidSize = 0; 42 int vidSize = 0; 43 44 int haveList = (NULL != pOidList); 45 46 char *pid = NULL; 47 char *vid = NULL; 48 49 di_node_t sv_node = DI_NODE_NIL; 50 di_node_t sv_child_node = DI_NODE_NIL; 51 52 int instNum; 53 int majorNum; 54 MP_UINT64 osn; 55 56 57 log(LOG_INFO, "getOidList()", " - enter"); 58 59 60 sv_node = di_drv_first_node("scsi_vhci", root_node); 61 if (DI_NODE_NIL == sv_node) { 62 log(LOG_INFO, "getOidList()", " - di_drv_first_node() failed"); 63 return (-1); 64 } 65 66 67 sv_child_node = di_child_node(sv_node); 68 69 while (DI_NODE_NIL != sv_child_node) { 70 71 (void) di_prop_lookup_strings(DDI_DEV_T_ANY, sv_child_node, 72 "inquiry-product-id", &pid); 73 74 pidSize = strlen(pid); 75 76 (void) di_prop_lookup_strings(DDI_DEV_T_ANY, sv_child_node, 77 "inquiry-vendor-id", &vid); 78 79 vidSize = strlen(vid); 80 81 if ((0 == strncmp(pProductID, pid, pidSize)) && 82 (0 == strncmp(pVendorID, vid, vidSize))) { 83 84 instNum = di_instance(sv_child_node); 85 majorNum = di_driver_major(sv_child_node); 86 87 if (haveList && numNodes < pOidList->oidCount) { 88 89 osn = 0; 90 osn = MP_STORE_INST_TO_ID(instNum, osn); 91 osn = MP_STORE_MAJOR_TO_ID(majorNum, osn); 92 93 pOidList->oids[numNodes].objectType = 94 MP_OBJECT_TYPE_MULTIPATH_LU; 95 96 pOidList->oids[numNodes].ownerId = 97 g_pluginOwnerID; 98 99 pOidList->oids[numNodes].objectSequenceNumber = 100 osn; 101 } 102 103 ++numNodes; 104 } 105 106 sv_child_node = di_sibling_node(sv_child_node); 107 } 108 109 110 log(LOG_INFO, "getOidList()", " - numNodes: %d", numNodes); 111 log(LOG_INFO, "getOidList()", " - exit"); 112 113 return (numNodes); 114 } 115 116 117 MP_STATUS 118 MP_GetMultipathLusDevProd(MP_OID oid, MP_OID_LIST **ppList) 119 { 120 di_node_t root_node = DI_NODE_NIL; 121 122 MP_STATUS mpStatus = MP_STATUS_SUCCESS; 123 124 int numNodes = 0; 125 int ioctlStatus = 0; 126 int i = 0; 127 128 mp_iocdata_t mp_ioctl; 129 mp_dev_prod_prop_t devProdInfo; 130 131 char inqProductID[256]; 132 char inqVendorID[256]; 133 134 135 log(LOG_INFO, "MP_GetMultipathLusDevProd()", " - enter"); 136 137 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 138 "oid.objectSequenceNumber = %llx", 139 oid.objectSequenceNumber); 140 141 if (g_scsi_vhci_fd < 0) { 142 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 143 "invalid driver file handle"); 144 log(LOG_INFO, "MP_GetMultipathLusDevProd", 145 " - error exit"); 146 return (MP_STATUS_FAILED); 147 } 148 149 (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t)); 150 (void) memset(&devProdInfo, 0, sizeof (mp_dev_prod_prop_t)); 151 152 mp_ioctl.mp_cmd = MP_GET_DEV_PROD_PROP; 153 mp_ioctl.mp_ibuf = (caddr_t)&oid.objectSequenceNumber; 154 mp_ioctl.mp_ilen = sizeof (oid.objectSequenceNumber); 155 mp_ioctl.mp_obuf = (caddr_t)&devProdInfo; 156 mp_ioctl.mp_olen = sizeof (mp_dev_prod_prop_t); 157 mp_ioctl.mp_xfer = MP_XFER_READ; 158 159 ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl); 160 161 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 162 " IOCTL call returned: %d", ioctlStatus); 163 164 if (ioctlStatus < 0) { 165 ioctlStatus = errno; 166 } 167 168 if (ioctlStatus != 0) { 169 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 170 "IOCTL call failed. IOCTL error is: %d", 171 ioctlStatus); 172 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 173 "IOCTL call failed. IOCTL error is: %s", 174 strerror(ioctlStatus)); 175 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 176 "IOCTL call failed. mp_ioctl.mp_errno: %x", 177 mp_ioctl.mp_errno); 178 179 if (ENOTSUP == ioctlStatus) { 180 mpStatus = MP_STATUS_UNSUPPORTED; 181 } else if (0 == mp_ioctl.mp_errno) { 182 mpStatus = MP_STATUS_FAILED; 183 } else { 184 mpStatus = getStatus4ErrorCode(mp_ioctl.mp_errno); 185 } 186 187 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 188 " - error exit"); 189 190 return (mpStatus); 191 } 192 193 (void) strncpy(inqProductID, devProdInfo.prodInfo.product, 194 sizeof (devProdInfo.prodInfo.product)); 195 196 (void) strncpy(inqVendorID, devProdInfo.prodInfo.vendor, 197 sizeof (devProdInfo.prodInfo.vendor)); 198 199 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 200 " - inqProductID: [%s]", inqProductID); 201 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 202 " - inqVendorID: [%s]", inqVendorID); 203 204 root_node = di_init("/", DINFOCACHE); 205 if (DI_NODE_NIL == root_node) { 206 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 207 " - di_init() failed"); 208 209 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 210 " - error exit"); 211 212 return (MP_STATUS_FAILED); 213 } 214 215 numNodes = getOidList(root_node, NULL, inqProductID, inqVendorID); 216 if (numNodes < 0) { 217 218 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 219 " - unable to get OID list."); 220 221 log(LOG_INFO, "MP_GetMultipathLusDevProd()", " - error exit"); 222 223 di_fini(root_node); 224 225 return (MP_STATUS_FAILED); 226 } 227 228 229 if (0 == numNodes) { 230 231 *ppList = createOidList(1); 232 if (NULL == *ppList) { 233 234 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 235 " - unable to create OID list."); 236 237 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 238 " - error exit"); 239 240 di_fini(root_node); 241 242 return (MP_STATUS_INSUFFICIENT_MEMORY); 243 } 244 245 (*ppList)->oids[0].objectType = MP_OBJECT_TYPE_MULTIPATH_LU; 246 (*ppList)->oids[0].ownerId = g_pluginOwnerID; 247 248 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 249 " - returning empty list."); 250 251 return (MP_STATUS_SUCCESS); 252 } 253 254 *ppList = createOidList(numNodes); 255 if (NULL == *ppList) { 256 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 257 "no memory for *ppList"); 258 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 259 " - error exit"); 260 return (MP_STATUS_INSUFFICIENT_MEMORY); 261 } 262 263 (*ppList)->oidCount = numNodes; 264 265 numNodes = getOidList(root_node, *ppList, inqProductID, inqVendorID); 266 267 for (i = 0; i < (*ppList)->oidCount; i++) { 268 269 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 270 "(*ppList)->oids[%d].objectType = %d", 271 i, (*ppList)->oids[i].objectType); 272 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 273 "(*ppList)->oids[%d].ownerId = %d", 274 i, (*ppList)->oids[i].ownerId); 275 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 276 "(*ppList)->oids[%d].objectSequenceNumber = %llx", 277 i, (*ppList)->oids[i].objectSequenceNumber); 278 } 279 280 281 di_fini(root_node); 282 283 log(LOG_INFO, "MP_GetMultipathLusDevProd()", " - exit"); 284 285 return (MP_STATUS_SUCCESS); 286 287 } 288