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
get_devlink(di_devlink_t devlink,void * arg)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
getDeviceFileName(MP_UINT64 objectSequenceNumber)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
MP_GetMPLogicalUnitProperties(MP_OID oid,MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES * pProps)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