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