xref: /illumos-gate/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetMultipathLusDevProd.c (revision e9af4bc0b1cc30cea75d6ad4aa2fde97d985e9be)
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 #include <libdevinfo.h>
32 
33 #include "mp_utils.h"
34 
35 
36 static int getOidList(di_node_t root_node,
37 			MP_OID_LIST *pOidList,
38 			char *pProductID,
39 			char *pVendorID)
40 {
41 	int numNodes = 0;
42 	int pidSize = 0;
43 	int vidSize = 0;
44 
45 	int haveList = (NULL != pOidList);
46 
47 	char *pid = NULL;
48 	char *vid = NULL;
49 
50 	di_node_t sv_node	= DI_NODE_NIL;
51 	di_node_t sv_child_node	= DI_NODE_NIL;
52 
53 	MP_UINT64 nodeInstance	= 0;
54 
55 
56 	log(LOG_INFO, "getOidList()", " - enter");
57 
58 
59 	sv_node = di_drv_first_node("scsi_vhci", root_node);
60 	if (DI_NODE_NIL == sv_node) {
61 		log(LOG_INFO, "getOidList()",
62 			" - di_drv_first_node() failed");
63 
64 		return (-1);
65 	}
66 
67 
68 	sv_child_node = di_child_node(sv_node);
69 
70 	while (DI_NODE_NIL != sv_child_node) {
71 
72 		(void) di_prop_lookup_strings(DDI_DEV_T_ANY,
73 			sv_child_node,
74 			"inquiry-product-id",
75 			&pid);
76 
77 		pidSize = strlen(pid);
78 
79 		(void) di_prop_lookup_strings(DDI_DEV_T_ANY,
80 			sv_child_node,
81 			"inquiry-vendor-id",
82 			&vid);
83 
84 		vidSize = strlen(vid);
85 
86 		if ((0 == strncmp(pProductID, pid, pidSize)) &&
87 		    (0 == strncmp(pVendorID, vid, vidSize))) {
88 
89 				if (haveList) {
90 
91 					nodeInstance =
92 						(MP_UINT64)
93 					    di_instance(sv_child_node);
94 
95 					if (numNodes < pOidList->oidCount) {
96 
97 						pOidList->oids[numNodes].
98 							objectType =
99 						MP_OBJECT_TYPE_MULTIPATH_LU;
100 
101 						pOidList->oids[numNodes].
102 							ownerId =
103 							g_pluginOwnerID;
104 
105 						pOidList->oids[numNodes].
106 							objectSequenceNumber =
107 							nodeInstance;
108 					}
109 				}
110 
111 			++numNodes;
112 		}
113 
114 		sv_child_node = di_sibling_node(sv_child_node);
115 	}
116 
117 
118 	log(LOG_INFO,
119 		"getOidList()",
120 		" - numNodes: %d",
121 		numNodes);
122 
123 
124 	log(LOG_INFO, "getOidList()", " - exit");
125 
126 	return (numNodes);
127 }
128 
129 
130 MP_STATUS
131 MP_GetMultipathLusDevProd(MP_OID oid, MP_OID_LIST **ppList)
132 {
133 	di_node_t root_node	= DI_NODE_NIL;
134 
135 	MP_STATUS mpStatus	= MP_STATUS_SUCCESS;
136 
137 	int numNodes = 0;
138 	int ioctlStatus = 0;
139 	int i = 0;
140 
141 	mp_iocdata_t		mp_ioctl;
142 	mp_dev_prod_prop_t	devProdInfo;
143 
144 	char inqProductID[256];
145 	char inqVendorID[256];
146 
147 
148 
149 	log(LOG_INFO, "MP_GetMultipathLusDevProd()", " - enter");
150 
151 
152 
153 	log(LOG_INFO, "MP_GetMultipathLusDevProd()",
154 		"oid.objectSequenceNumber = %llx",
155 		oid.objectSequenceNumber);
156 
157 	if (g_scsi_vhci_fd < 0) {
158 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
159 		    "invalid driver file handle");
160 		log(LOG_INFO, "MP_GetMultipathLusDevProd",
161 			" - error exit");
162 		return (MP_STATUS_FAILED);
163 	}
164 
165 	(void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
166 	(void) memset(&devProdInfo, 0, sizeof (mp_dev_prod_prop_t));
167 
168 	mp_ioctl.mp_cmd  = MP_GET_DEV_PROD_PROP;
169 	mp_ioctl.mp_ibuf = (caddr_t)&oid.objectSequenceNumber;
170 	mp_ioctl.mp_ilen = sizeof (oid.objectSequenceNumber);
171 	mp_ioctl.mp_obuf = (caddr_t)&devProdInfo;
172 	mp_ioctl.mp_olen = sizeof (mp_dev_prod_prop_t);
173 	mp_ioctl.mp_xfer = MP_XFER_READ;
174 
175 	ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
176 
177 	log(LOG_INFO, "MP_GetMultipathLusDevProd()",
178 		" IOCTL call returned: %d", ioctlStatus);
179 
180 	if (ioctlStatus < 0) {
181 		ioctlStatus = errno;
182 	}
183 
184 	if (ioctlStatus != 0) {
185 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
186 		    "IOCTL call failed.  IOCTL error is: %d",
187 			ioctlStatus);
188 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
189 		    "IOCTL call failed.  IOCTL error is: %s",
190 			strerror(ioctlStatus));
191 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
192 		    "IOCTL call failed.  mp_ioctl.mp_errno: %x",
193 			mp_ioctl.mp_errno);
194 
195 		if (ENOTSUP == ioctlStatus) {
196 			mpStatus = MP_STATUS_UNSUPPORTED;
197 		} else if (0 == mp_ioctl.mp_errno) {
198 			mpStatus = MP_STATUS_FAILED;
199 		} else {
200 			mpStatus = getStatus4ErrorCode(mp_ioctl.mp_errno);
201 		}
202 
203 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
204 			" - error exit");
205 
206 		return (mpStatus);
207 	}
208 
209 	(void) strncpy(inqProductID,
210 			devProdInfo.prodInfo.product,
211 			sizeof (devProdInfo.prodInfo.product));
212 
213 	(void) strncpy(inqVendorID,
214 			devProdInfo.prodInfo.vendor,
215 			sizeof (devProdInfo.prodInfo.vendor));
216 
217 	log(LOG_INFO, "MP_GetMultipathLusDevProd()",
218 		" - inqProductID:  [%s]", inqProductID);
219 	log(LOG_INFO, "MP_GetMultipathLusDevProd()",
220 		" - inqVendorID:   [%s]", inqVendorID);
221 
222 
223 	root_node = di_init("/", DINFOCACHE);
224 	if (DI_NODE_NIL == root_node) {
225 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
226 			" - di_init() failed");
227 
228 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
229 			" - error exit");
230 
231 		return (MP_STATUS_FAILED);
232 	}
233 
234 	numNodes = getOidList(root_node,
235 				NULL,
236 				inqProductID,
237 				inqVendorID);
238 
239 	if (numNodes < 0) {
240 
241 		log(LOG_INFO,
242 			"MP_GetMultipathLusDevProd()",
243 			" - unable to get OID list.");
244 
245 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
246 			" - error exit");
247 
248 		di_fini(root_node);
249 
250 		return (MP_STATUS_FAILED);
251 	}
252 
253 
254 	if (0 == numNodes) {
255 
256 		*ppList = createOidList(1);
257 		if (NULL == *ppList) {
258 
259 			log(LOG_INFO,
260 				"MP_GetMultipathLusDevProd()",
261 				" - unable to create OID list.");
262 
263 			log(LOG_INFO, "MP_GetMultipathLusDevProd()",
264 				" - error exit");
265 
266 			di_fini(root_node);
267 
268 			return (MP_STATUS_INSUFFICIENT_MEMORY);
269 		}
270 
271 		(*ppList)->oids[0].objectType =
272 			MP_OBJECT_TYPE_MULTIPATH_LU;
273 
274 		(*ppList)->oids[0].ownerId =
275 			g_pluginOwnerID;
276 
277 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
278 			" - returning empty list.");
279 
280 		return (MP_STATUS_SUCCESS);
281 	}
282 
283 	*ppList = createOidList(numNodes);
284 	if (NULL == *ppList) {
285 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
286 			"no memory for *ppList");
287 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
288 			" - error exit");
289 		return (MP_STATUS_INSUFFICIENT_MEMORY);
290 	}
291 
292 	(*ppList)->oidCount = numNodes;
293 
294 	numNodes = getOidList(root_node,
295 				*ppList,
296 				inqProductID,
297 				inqVendorID);
298 
299 
300 	for (i = 0; i < (*ppList)->oidCount; i++) {
301 
302 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
303 			"(*ppList)->oids[%d].objectType           = %d",
304 			i, (*ppList)->oids[i].objectType);
305 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
306 			"(*ppList)->oids[%d].ownerId              = %d",
307 			i, (*ppList)->oids[i].ownerId);
308 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
309 			"(*ppList)->oids[%d].objectSequenceNumber = %llx",
310 			i, (*ppList)->oids[i].objectSequenceNumber);
311 	}
312 
313 
314 	di_fini(root_node);
315 
316 	log(LOG_INFO, "MP_GetMultipathLusDevProd()", " - exit");
317 
318 	return (MP_STATUS_SUCCESS);
319 
320 }
321