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