xref: /illumos-gate/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetMPLogicalUnitProperties.c (revision d67944fbe3fa0b31893a7116a09b0718eecf6078)
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 2009 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 = (MP_UINT64)di_instance(cur_node);
116 
117 		if (nodeInstance == instanceNum) {
118 
119 			log(LOG_INFO, "getDeviceFileName()",
120 			    " - found node.");
121 
122 			break;
123 		}
124 
125 		cur_node = di_sibling_node(cur_node);
126 	}
127 
128 	if (DI_NODE_NIL != cur_node) {
129 
130 		dlHandle = di_devlink_init(NULL, 0);
131 		if (NULL == dlHandle) {
132 			log(LOG_INFO, "getDeviceFileName()",
133 			    " - $ERROR, di_devlink_init() failed.");
134 
135 			di_fini(root_node);
136 
137 			return (NULL);
138 		}
139 
140 		pathName = di_devfs_path(cur_node);
141 
142 		(void) snprintf(fullName, 511, "%s:%s", pathName, minorName);
143 
144 		log(LOG_INFO, "getDeviceFileName()",
145 		    " - fullName: {%s]", fullName);
146 
147 		(void) memset(&warg, 0, sizeof (walk_devlink_t));
148 
149 		devLink  = NULL;
150 		warg.linkpp = &devLink;
151 
152 		diStatus = di_devlink_walk(dlHandle,
153 		    NULL,
154 		    fullName,
155 		    DI_PRIMARY_LINK,
156 		    (void *)&warg,
157 		    get_devlink);
158 
159 		if (diStatus != 0) {
160 
161 			log(LOG_INFO, "getDeviceFileName()",
162 			    "diStatus: %d", diStatus);
163 
164 			if (diStatus < 0) {
165 				diStatus = errno;
166 			}
167 
168 			log(LOG_INFO, "getDeviceFileName()",
169 			    "diStatus: %d", diStatus);
170 
171 			log(LOG_INFO, "getDeviceFileName()",
172 			    "strerror(diStatus): %s", strerror(diStatus));
173 		}
174 
175 		if (NULL != devLink) {
176 
177 			deviceFileName =
178 			    (char *)calloc(1, strlen(devLink) + 1);
179 
180 			(void) strncpy(deviceFileName, devLink,
181 			    strlen(devLink));
182 
183 		} else {
184 
185 			log(LOG_INFO, "getDeviceFileName()",
186 			    " - $ERROR, devLink is NULL.");
187 
188 			deviceFileName =
189 			    (char *)calloc(1, 256);
190 
191 			(void) strncpy(deviceFileName, pathName, 255);
192 		}
193 
194 		di_devfs_path_free(pathName);
195 
196 		(void) di_devlink_fini(&dlHandle);
197 
198 	}
199 
200 
201 	di_fini(root_node);
202 
203 	free(devLink);
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