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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <string.h> 27 #include <syslog.h> 28 #include <errno.h> 29 #include <unistd.h> 30 #include <stropts.h> 31 #include <libdevinfo.h> 32 33 #include "mp_utils.h" 34 35 36 static int getOidList(di_node_t root_node, 37 MP_OID_LIST *pOidList, 38 char *pProductID, 39 char *pVendorID) 40 { 41 int numNodes = 0; 42 int pidSize = 0; 43 int vidSize = 0; 44 45 int haveList = (NULL != pOidList); 46 47 char *pid = NULL; 48 char *vid = NULL; 49 50 di_node_t sv_node = DI_NODE_NIL; 51 di_node_t sv_child_node = DI_NODE_NIL; 52 53 MP_UINT64 nodeInstance = 0; 54 55 56 log(LOG_INFO, "getOidList()", " - enter"); 57 58 59 sv_node = di_drv_first_node("scsi_vhci", root_node); 60 if (DI_NODE_NIL == sv_node) { 61 log(LOG_INFO, "getOidList()", 62 " - di_drv_first_node() failed"); 63 64 return (-1); 65 } 66 67 68 sv_child_node = di_child_node(sv_node); 69 70 while (DI_NODE_NIL != sv_child_node) { 71 72 (void) di_prop_lookup_strings(DDI_DEV_T_ANY, 73 sv_child_node, 74 "inquiry-product-id", 75 &pid); 76 77 pidSize = strlen(pid); 78 79 (void) di_prop_lookup_strings(DDI_DEV_T_ANY, 80 sv_child_node, 81 "inquiry-vendor-id", 82 &vid); 83 84 vidSize = strlen(vid); 85 86 if ((0 == strncmp(pProductID, pid, pidSize)) && 87 (0 == strncmp(pVendorID, vid, vidSize))) { 88 89 if (haveList) { 90 91 nodeInstance = 92 (MP_UINT64) 93 di_instance(sv_child_node); 94 95 if (numNodes < pOidList->oidCount) { 96 97 pOidList->oids[numNodes]. 98 objectType = 99 MP_OBJECT_TYPE_MULTIPATH_LU; 100 101 pOidList->oids[numNodes]. 102 ownerId = 103 g_pluginOwnerID; 104 105 pOidList->oids[numNodes]. 106 objectSequenceNumber = 107 nodeInstance; 108 } 109 } 110 111 ++numNodes; 112 } 113 114 sv_child_node = di_sibling_node(sv_child_node); 115 } 116 117 118 log(LOG_INFO, 119 "getOidList()", 120 " - numNodes: %d", 121 numNodes); 122 123 124 log(LOG_INFO, "getOidList()", " - exit"); 125 126 return (numNodes); 127 } 128 129 130 MP_STATUS 131 MP_GetMultipathLusDevProd(MP_OID oid, MP_OID_LIST **ppList) 132 { 133 di_node_t root_node = DI_NODE_NIL; 134 135 MP_STATUS mpStatus = MP_STATUS_SUCCESS; 136 137 int numNodes = 0; 138 int ioctlStatus = 0; 139 int i = 0; 140 141 mp_iocdata_t mp_ioctl; 142 mp_dev_prod_prop_t devProdInfo; 143 144 char inqProductID[256]; 145 char inqVendorID[256]; 146 147 148 149 log(LOG_INFO, "MP_GetMultipathLusDevProd()", " - enter"); 150 151 152 153 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 154 "oid.objectSequenceNumber = %llx", 155 oid.objectSequenceNumber); 156 157 if (g_scsi_vhci_fd < 0) { 158 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 159 "invalid driver file handle"); 160 log(LOG_INFO, "MP_GetMultipathLusDevProd", 161 " - error exit"); 162 return (MP_STATUS_FAILED); 163 } 164 165 (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t)); 166 (void) memset(&devProdInfo, 0, sizeof (mp_dev_prod_prop_t)); 167 168 mp_ioctl.mp_cmd = MP_GET_DEV_PROD_PROP; 169 mp_ioctl.mp_ibuf = (caddr_t)&oid.objectSequenceNumber; 170 mp_ioctl.mp_ilen = sizeof (oid.objectSequenceNumber); 171 mp_ioctl.mp_obuf = (caddr_t)&devProdInfo; 172 mp_ioctl.mp_olen = sizeof (mp_dev_prod_prop_t); 173 mp_ioctl.mp_xfer = MP_XFER_READ; 174 175 ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl); 176 177 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 178 " IOCTL call returned: %d", ioctlStatus); 179 180 if (ioctlStatus < 0) { 181 ioctlStatus = errno; 182 } 183 184 if (ioctlStatus != 0) { 185 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 186 "IOCTL call failed. IOCTL error is: %d", 187 ioctlStatus); 188 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 189 "IOCTL call failed. IOCTL error is: %s", 190 strerror(ioctlStatus)); 191 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 192 "IOCTL call failed. mp_ioctl.mp_errno: %x", 193 mp_ioctl.mp_errno); 194 195 if (ENOTSUP == ioctlStatus) { 196 mpStatus = MP_STATUS_UNSUPPORTED; 197 } else if (0 == mp_ioctl.mp_errno) { 198 mpStatus = MP_STATUS_FAILED; 199 } else { 200 mpStatus = getStatus4ErrorCode(mp_ioctl.mp_errno); 201 } 202 203 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 204 " - error exit"); 205 206 return (mpStatus); 207 } 208 209 (void) strncpy(inqProductID, 210 devProdInfo.prodInfo.product, 211 sizeof (devProdInfo.prodInfo.product)); 212 213 (void) strncpy(inqVendorID, 214 devProdInfo.prodInfo.vendor, 215 sizeof (devProdInfo.prodInfo.vendor)); 216 217 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 218 " - inqProductID: [%s]", inqProductID); 219 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 220 " - inqVendorID: [%s]", inqVendorID); 221 222 223 root_node = di_init("/", DINFOCACHE); 224 if (DI_NODE_NIL == root_node) { 225 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 226 " - di_init() failed"); 227 228 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 229 " - error exit"); 230 231 return (MP_STATUS_FAILED); 232 } 233 234 numNodes = getOidList(root_node, 235 NULL, 236 inqProductID, 237 inqVendorID); 238 239 if (numNodes < 0) { 240 241 log(LOG_INFO, 242 "MP_GetMultipathLusDevProd()", 243 " - unable to get OID list."); 244 245 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 246 " - error exit"); 247 248 di_fini(root_node); 249 250 return (MP_STATUS_FAILED); 251 } 252 253 254 if (0 == numNodes) { 255 256 *ppList = createOidList(1); 257 if (NULL == *ppList) { 258 259 log(LOG_INFO, 260 "MP_GetMultipathLusDevProd()", 261 " - unable to create OID list."); 262 263 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 264 " - error exit"); 265 266 di_fini(root_node); 267 268 return (MP_STATUS_INSUFFICIENT_MEMORY); 269 } 270 271 (*ppList)->oids[0].objectType = 272 MP_OBJECT_TYPE_MULTIPATH_LU; 273 274 (*ppList)->oids[0].ownerId = 275 g_pluginOwnerID; 276 277 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 278 " - returning empty list."); 279 280 return (MP_STATUS_SUCCESS); 281 } 282 283 *ppList = createOidList(numNodes); 284 if (NULL == *ppList) { 285 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 286 "no memory for *ppList"); 287 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 288 " - error exit"); 289 return (MP_STATUS_INSUFFICIENT_MEMORY); 290 } 291 292 (*ppList)->oidCount = numNodes; 293 294 numNodes = getOidList(root_node, 295 *ppList, 296 inqProductID, 297 inqVendorID); 298 299 300 for (i = 0; i < (*ppList)->oidCount; i++) { 301 302 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 303 "(*ppList)->oids[%d].objectType = %d", 304 i, (*ppList)->oids[i].objectType); 305 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 306 "(*ppList)->oids[%d].ownerId = %d", 307 i, (*ppList)->oids[i].ownerId); 308 log(LOG_INFO, "MP_GetMultipathLusDevProd()", 309 "(*ppList)->oids[%d].objectSequenceNumber = %llx", 310 i, (*ppList)->oids[i].objectSequenceNumber); 311 } 312 313 314 di_fini(root_node); 315 316 log(LOG_INFO, "MP_GetMultipathLusDevProd()", " - exit"); 317 318 return (MP_STATUS_SUCCESS); 319 320 } 321