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