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 31 #include <libdevinfo.h> 32 33 #include "mp_utils.h" 34 35 36 typedef struct walk_devlink { 37 char *path; 38 size_t len; 39 char **linkpp; 40 } walk_devlink_t; 41 42 43 44 static int 45 get_devlink(di_devlink_t devlink, void *arg) { 46 47 walk_devlink_t *warg = (walk_devlink_t *)arg; 48 49 50 log(LOG_INFO, "get_devlink()", " - enter"); 51 52 53 *(warg->linkpp) = strdup(di_devlink_path(devlink)); 54 55 56 log(LOG_INFO, "get_devlink()", " - exit"); 57 58 return (DI_WALK_TERMINATE); 59 } 60 61 62 char 63 *getDeviceFileName(MP_UINT64 objectSequenceNumber) 64 { 65 char *deviceFileName = NULL; 66 67 di_node_t root_node = DI_NODE_NIL; 68 di_node_t cur_node = DI_NODE_NIL; 69 70 int instNum; 71 int majorNum; 72 MP_UINT64 osn; 73 74 char *pathName = NULL; 75 char *minorName = "c,raw"; 76 char *devLink = NULL; 77 78 char fullName[512]; 79 80 walk_devlink_t warg; 81 di_devlink_handle_t dlHandle = NULL; 82 83 int diStatus = 0; 84 85 86 log(LOG_INFO, "getDeviceFileName()", " - enter"); 87 88 log(LOG_INFO, "getDeviceFileName()", 89 " - objectSequenceNumber: %llx", 90 objectSequenceNumber); 91 92 root_node = di_init("/", DINFOCACHE); 93 if (DI_NODE_NIL == root_node) { 94 log(LOG_INFO, "MP_GetMultipathLusPlugin()", 95 " - $ERROR, di_init() failed"); 96 97 return (NULL); 98 } 99 100 101 cur_node = di_drv_first_node("scsi_vhci", root_node); 102 if (DI_NODE_NIL == cur_node) { 103 log(LOG_INFO, "getDeviceFileName()", 104 " - $ERROR, di_drv_first_node() failed"); 105 106 di_fini(root_node); 107 108 return (NULL); 109 } 110 111 112 cur_node = di_child_node(cur_node); 113 114 while (DI_NODE_NIL != cur_node) { 115 116 instNum = di_instance(cur_node); 117 majorNum = di_driver_major(cur_node); 118 119 osn = 0; 120 osn = MP_STORE_INST_TO_ID(instNum, osn); 121 osn = MP_STORE_MAJOR_TO_ID(majorNum, osn); 122 123 if (osn == objectSequenceNumber) { 124 125 log(LOG_INFO, "getDeviceFileName()", 126 " - found node."); 127 128 break; 129 } 130 131 cur_node = di_sibling_node(cur_node); 132 } 133 134 if (DI_NODE_NIL != cur_node) { 135 136 dlHandle = di_devlink_init(NULL, 0); 137 if (NULL == dlHandle) { 138 log(LOG_INFO, "getDeviceFileName()", 139 " - $ERROR, di_devlink_init() failed."); 140 141 di_fini(root_node); 142 143 return (NULL); 144 } 145 146 pathName = di_devfs_path(cur_node); 147 148 (void) snprintf(fullName, 511, "%s:%s", pathName, minorName); 149 150 log(LOG_INFO, "getDeviceFileName()", 151 " - fullName: {%s]", fullName); 152 153 (void) memset(&warg, 0, sizeof (walk_devlink_t)); 154 155 devLink = NULL; 156 warg.linkpp = &devLink; 157 158 diStatus = di_devlink_walk(dlHandle, 159 NULL, 160 fullName, 161 DI_PRIMARY_LINK, 162 (void *)&warg, 163 get_devlink); 164 165 if (diStatus != 0) { 166 167 log(LOG_INFO, "getDeviceFileName()", 168 "diStatus: %d", diStatus); 169 170 if (diStatus < 0) { 171 diStatus = errno; 172 } 173 174 log(LOG_INFO, "getDeviceFileName()", 175 "diStatus: %d", diStatus); 176 177 log(LOG_INFO, "getDeviceFileName()", 178 "strerror(diStatus): %s", strerror(diStatus)); 179 } 180 181 if (NULL != devLink) { 182 183 deviceFileName = 184 (char *)calloc(1, strlen(devLink) + 1); 185 186 (void) strncpy(deviceFileName, devLink, 187 strlen(devLink)); 188 189 } else { 190 191 log(LOG_INFO, "getDeviceFileName()", 192 " - $ERROR, devLink is NULL."); 193 194 deviceFileName = 195 (char *)calloc(1, 256); 196 197 (void) strncpy(deviceFileName, pathName, 255); 198 } 199 200 di_devfs_path_free(pathName); 201 202 (void) di_devlink_fini(&dlHandle); 203 204 } 205 206 207 di_fini(root_node); 208 209 free(devLink); 210 211 log(LOG_INFO, "getDeviceFileName()", " - exit"); 212 213 return (deviceFileName); 214 } 215 216 217 218 MP_STATUS 219 MP_GetMPLogicalUnitProperties(MP_OID oid, 220 MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES *pProps) 221 { 222 mp_iocdata_t mp_ioctl; 223 mp_logical_unit_prop_t luInfo; 224 225 MP_OID overridePathOID; 226 227 int ioctlStatus = 0; 228 229 int vendorLength = 0; 230 int productLength = 0; 231 int revisionLength = 0; 232 233 char *deviceFileName = NULL; 234 235 236 MP_STATUS mpStatus = MP_STATUS_SUCCESS; 237 238 239 log(LOG_INFO, "MP_GetMPLogicalUnitProperties()", " - enter"); 240 241 242 log(LOG_INFO, "MP_GetMPLogicalUnitProperties()", 243 "oid.objectSequenceNumber = %llx", 244 oid.objectSequenceNumber); 245 246 if (g_scsi_vhci_fd < 0) { 247 log(LOG_INFO, "MP_GetMPLogicalUnitProperties()", 248 "invalid driver file handle"); 249 log(LOG_INFO, "MP_GetMPLogicalUnitProperties()", 250 " - error exit"); 251 return (MP_STATUS_FAILED); 252 } 253 254 (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t)); 255 (void) memset(&luInfo, 0, sizeof (mp_logical_unit_prop_t)); 256 257 mp_ioctl.mp_cmd = MP_GET_LU_PROP; 258 mp_ioctl.mp_ibuf = (caddr_t)&oid.objectSequenceNumber; 259 mp_ioctl.mp_ilen = sizeof (oid.objectSequenceNumber); 260 mp_ioctl.mp_obuf = (caddr_t)&luInfo; 261 mp_ioctl.mp_olen = sizeof (mp_logical_unit_prop_t); 262 mp_ioctl.mp_xfer = MP_XFER_READ; 263 264 ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl); 265 266 log(LOG_INFO, "MP_GetMPLogicalUnitProperties()", 267 " IOCTL call returned: %d", ioctlStatus); 268 269 if (ioctlStatus < 0) { 270 ioctlStatus = errno; 271 } 272 273 if (ioctlStatus != 0) { 274 log(LOG_INFO, "MP_GetMPLogicalUnitProperties()", 275 "IOCTL call failed. IOCTL error is: %d", 276 ioctlStatus); 277 log(LOG_INFO, "MP_GetMPLogicalUnitProperties()", 278 "IOCTL call failed. IOCTL error is: %s", 279 strerror(ioctlStatus)); 280 log(LOG_INFO, "MP_GetMPLogicalUnitProperties()", 281 "IOCTL call failed. mp_ioctl.mp_errno: %x", 282 mp_ioctl.mp_errno); 283 284 if (ENOTSUP == ioctlStatus) { 285 mpStatus = MP_STATUS_UNSUPPORTED; 286 } else if (0 == mp_ioctl.mp_errno) { 287 mpStatus = MP_STATUS_FAILED; 288 } else { 289 mpStatus = getStatus4ErrorCode(mp_ioctl.mp_errno); 290 } 291 292 log(LOG_INFO, "MP_GetMPLogicalUnitProperties()", 293 " - error exit"); 294 295 return (mpStatus); 296 } 297 298 (void) memset(pProps, 0, sizeof (MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES)); 299 300 pProps->asymmetric = luInfo.asymmetric; 301 pProps->autoFailbackEnabled = luInfo.autoFailbackEnabled; 302 pProps->autoProbingEnabled = luInfo.autoProbingEnabled; 303 pProps->currentFailbackPollingRate = luInfo.currentFailBackPollingRate; 304 pProps->currentLoadBalanceType = luInfo.currentLoadBalanceType; 305 pProps->currentProbingPollingRate = luInfo.currentProbingPollingRate; 306 307 308 deviceFileName = getDeviceFileName(oid.objectSequenceNumber); 309 310 if (NULL != deviceFileName) { 311 312 log(LOG_INFO, "MP_GetMPLogicalUnitProperties()", 313 "deviceFileName: %s", 314 deviceFileName); 315 316 (void) strncpy(pProps->deviceFileName, 317 deviceFileName, 318 sizeof (pProps->deviceFileName) - 1); 319 320 free(deviceFileName); 321 } 322 323 pProps->failbackPollingRateMax = luInfo.failbackPollingRateMax; 324 pProps->logicalUnitGroupID = luInfo.luGroupID; 325 326 (void) strncpy(pProps->name, luInfo.name, sizeof (pProps->name) - 1); 327 328 pProps->nameType = luInfo.nameType; 329 330 overridePathOID.objectSequenceNumber = luInfo.overridePathID; 331 overridePathOID.objectType = MP_OBJECT_TYPE_PATH_LU; 332 overridePathOID.ownerId = g_pluginOwnerID; 333 (void) memcpy(&pProps->overridePath, &overridePathOID, sizeof (MP_OID)); 334 335 pProps->probingPollingRateMax = luInfo.probingPollingRateMax; 336 337 338 vendorLength = sizeof (pProps->vendor); 339 productLength = sizeof (pProps->product); 340 revisionLength = sizeof (pProps->revision); 341 342 (void) strncpy(pProps->vendor, 343 luInfo.prodInfo.vendor, 344 vendorLength); 345 346 (void) strncpy(pProps->product, 347 luInfo.prodInfo.product, 348 productLength); 349 350 (void) strncpy(pProps->revision, 351 luInfo.prodInfo.revision, 352 revisionLength); 353 354 log(LOG_INFO, "MP_GetMPLogicalUnitProperties()", " - exit"); 355 356 return (MP_STATUS_SUCCESS); 357 } 358