1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte  * CDDL HEADER START
3fcf3ce44SJohn Forte  *
4fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte  *
8fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte  * and limitations under the License.
12fcf3ce44SJohn Forte  *
13fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte  *
19fcf3ce44SJohn Forte  * CDDL HEADER END
20fcf3ce44SJohn Forte  */
21fcf3ce44SJohn Forte /*
22*0c034175SJiri Svoboda  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
23fcf3ce44SJohn Forte  */
24fcf3ce44SJohn Forte 
25fcf3ce44SJohn Forte #include <syslog.h>
26fcf3ce44SJohn Forte #include <errno.h>
27fcf3ce44SJohn Forte #include <unistd.h>
28fcf3ce44SJohn Forte #include <stropts.h>
29fcf3ce44SJohn Forte 
30fcf3ce44SJohn Forte #include "mp_utils.h"
31fcf3ce44SJohn Forte 
32fcf3ce44SJohn Forte #include <libdevinfo.h>
33fcf3ce44SJohn Forte 
344c06356bSdh /*
354c06356bSdh  * Checks whether there is online path or not.
364c06356bSdh  *  - no path found returns -1.
374c06356bSdh  *  - online/standby path found returns 1.
384c06356bSdh  *  - path exists but no online/standby path found returns 0.
394c06356bSdh  */
checkAvailablePath(di_node_t node)404c06356bSdh static int checkAvailablePath(di_node_t node)
414c06356bSdh {
424c06356bSdh 	di_path_t path;
434c06356bSdh 	di_path_state_t state;
444c06356bSdh 
454c06356bSdh 	if ((path = di_path_client_next_path(node, DI_PATH_NIL))
464c06356bSdh 	    == DI_PATH_NIL) {
474c06356bSdh 		log(LOG_INFO, "checkAvailalblePath()",
484c06356bSdh 		    " - No path found");
494c06356bSdh 		return (-1);
504c06356bSdh 	}
514c06356bSdh 
524c06356bSdh 	do {
534c06356bSdh 		/* ignore the path that is neither online nor standby. */
544c06356bSdh 		if (((state = di_path_state(path)) == DI_PATH_STATE_ONLINE) ||
554c06356bSdh 		    (state == DI_PATH_STATE_STANDBY)) {
564c06356bSdh 			return (1);
574c06356bSdh 		}
584c06356bSdh 	} while ((path = di_path_client_next_path(node, path)) != DI_PATH_NIL);
594c06356bSdh 
604c06356bSdh 	/* return 0 for the case that there is no online path to the node. */
614c06356bSdh 	log(LOG_INFO, "checkAvailalblePath()", " - No online path found");
624c06356bSdh 	return (0);
634c06356bSdh }
644c06356bSdh 
getOidList(di_node_t root_node,MP_OID_LIST * pOidList)65fcf3ce44SJohn Forte static int getOidList(di_node_t root_node, MP_OID_LIST *pOidList)
66fcf3ce44SJohn Forte {
674c06356bSdh 	int numNodes = 0, state;
68fcf3ce44SJohn Forte 
69*0c034175SJiri Svoboda 	int instNum;
70*0c034175SJiri Svoboda 	int majorNum;
71*0c034175SJiri Svoboda 	MP_UINT64 osn;
72fcf3ce44SJohn Forte 
73fcf3ce44SJohn Forte 	di_node_t sv_node	= DI_NODE_NIL;
74fcf3ce44SJohn Forte 	di_node_t sv_child_node = DI_NODE_NIL;
75fcf3ce44SJohn Forte 
76fcf3ce44SJohn Forte 	int haveList = (NULL != pOidList);
77fcf3ce44SJohn Forte 
78fcf3ce44SJohn Forte 
79fcf3ce44SJohn Forte 	log(LOG_INFO, "getOidList()", " - enter");
80fcf3ce44SJohn Forte 
81fcf3ce44SJohn Forte 
82fcf3ce44SJohn Forte 	sv_node = di_drv_first_node("scsi_vhci", root_node);
83fcf3ce44SJohn Forte 	if (DI_NODE_NIL == sv_node) {
84fcf3ce44SJohn Forte 		log(LOG_INFO, "getOidList()",
85fcf3ce44SJohn Forte 		    " - di_drv_first_node() failed");
86fcf3ce44SJohn Forte 
87fcf3ce44SJohn Forte 		return (-1);
88fcf3ce44SJohn Forte 	}
89fcf3ce44SJohn Forte 
90fcf3ce44SJohn Forte 	sv_child_node = di_child_node(sv_node);
91fcf3ce44SJohn Forte 
92fcf3ce44SJohn Forte 	while (DI_NODE_NIL != sv_child_node) {
93fcf3ce44SJohn Forte 
944c06356bSdh 		/* skip the node which is offline, down or detached. */
954c06356bSdh 		state = di_state(sv_child_node);
964c06356bSdh 		if ((state & DI_DEVICE_DOWN) ||
974c06356bSdh 		    (state & DI_DEVICE_OFFLINE)) {
984c06356bSdh 			sv_child_node = di_sibling_node(sv_child_node);
994c06356bSdh 			continue;
1004c06356bSdh 		}
1014c06356bSdh 
1024c06356bSdh 		/*
1034c06356bSdh 		 * skip if the node doesn't have any path avaialble.
1044c06356bSdh 		 * If any path is found from the DINFOCACHE snaphost
1054c06356bSdh 		 * that means the driver keeps track of the path regadless
1064c06356bSdh 		 * of state.
1074c06356bSdh 		 */
1084c06356bSdh 		if (checkAvailablePath(sv_child_node) == -1) {
109466684c0SJiri Svoboda 			sv_child_node = di_sibling_node(sv_child_node);
110466684c0SJiri Svoboda 			continue;
111466684c0SJiri Svoboda 		}
112fcf3ce44SJohn Forte 
113466684c0SJiri Svoboda 		if (haveList && (numNodes < pOidList->oidCount)) {
114*0c034175SJiri Svoboda 			instNum = di_instance(sv_child_node);
115*0c034175SJiri Svoboda 			majorNum = di_driver_major(sv_child_node);
1160c3de118SChris Liu 
117fcf3ce44SJohn Forte 			log(LOG_INFO, "getOidList()",
118*0c034175SJiri Svoboda 			    "instNum = %d", instNum);
119*0c034175SJiri Svoboda 			log(LOG_INFO, "getOidList()",
120*0c034175SJiri Svoboda 			    "majorNum = %d", majorNum);
121*0c034175SJiri Svoboda 
122*0c034175SJiri Svoboda 			osn = 0;
123*0c034175SJiri Svoboda 			osn = MP_STORE_INST_TO_ID(instNum, osn);
124*0c034175SJiri Svoboda 			osn = MP_STORE_MAJOR_TO_ID(majorNum, osn);
125fcf3ce44SJohn Forte 
126fcf3ce44SJohn Forte 			pOidList->oids[numNodes].objectType =
1270c3de118SChris Liu 			    MP_OBJECT_TYPE_MULTIPATH_LU;
128fcf3ce44SJohn Forte 
129fcf3ce44SJohn Forte 			pOidList->oids[numNodes].ownerId =
1300c3de118SChris Liu 			    g_pluginOwnerID;
131fcf3ce44SJohn Forte 
132fcf3ce44SJohn Forte 			pOidList->oids[numNodes].objectSequenceNumber =
133*0c034175SJiri Svoboda 			    osn;
134fcf3ce44SJohn Forte 		}
135fcf3ce44SJohn Forte 
136fcf3ce44SJohn Forte 		++numNodes;
137fcf3ce44SJohn Forte 
138fcf3ce44SJohn Forte 		sv_child_node = di_sibling_node(sv_child_node);
139fcf3ce44SJohn Forte 	}
140fcf3ce44SJohn Forte 
141fcf3ce44SJohn Forte 	log(LOG_INFO,
142fcf3ce44SJohn Forte 	    "getOidList()",
143fcf3ce44SJohn Forte 	    " - numNodes: %d",
144fcf3ce44SJohn Forte 	    numNodes);
145fcf3ce44SJohn Forte 
146fcf3ce44SJohn Forte 
147fcf3ce44SJohn Forte 
148fcf3ce44SJohn Forte 	log(LOG_INFO, "getOidList()", " - exit");
149fcf3ce44SJohn Forte 
150fcf3ce44SJohn Forte 	return (numNodes);
151fcf3ce44SJohn Forte }
152fcf3ce44SJohn Forte 
153fcf3ce44SJohn Forte 
154fcf3ce44SJohn Forte MP_STATUS
MP_GetMultipathLusPlugin(MP_OID_LIST ** ppList)155fcf3ce44SJohn Forte MP_GetMultipathLusPlugin(MP_OID_LIST **ppList)
156fcf3ce44SJohn Forte {
157fcf3ce44SJohn Forte 	di_node_t root_node	= DI_NODE_NIL;
158fcf3ce44SJohn Forte 	MP_OID_LIST *pOidList   = NULL;
159fcf3ce44SJohn Forte 
160fcf3ce44SJohn Forte 	int numNodes = 0;
161fcf3ce44SJohn Forte 	int i = 0;
162fcf3ce44SJohn Forte 
163fcf3ce44SJohn Forte 	log(LOG_INFO, "MP_GetMultipathLusPlugin()", " - enter");
164fcf3ce44SJohn Forte 
165fcf3ce44SJohn Forte 
166fcf3ce44SJohn Forte 	root_node = di_init("/", DINFOCACHE);
167fcf3ce44SJohn Forte 	if (DI_NODE_NIL == root_node) {
168fcf3ce44SJohn Forte 		log(LOG_INFO, "MP_GetMultipathLusPlugin()",
169fcf3ce44SJohn Forte 		    " - di_init() failed");
170fcf3ce44SJohn Forte 
171fcf3ce44SJohn Forte 		return (MP_STATUS_FAILED);
172fcf3ce44SJohn Forte 	}
173fcf3ce44SJohn Forte 
174fcf3ce44SJohn Forte 	numNodes = getOidList(root_node, NULL);
175fcf3ce44SJohn Forte 
176fcf3ce44SJohn Forte 	if (numNodes < 0) {
177fcf3ce44SJohn Forte 
178fcf3ce44SJohn Forte 		log(LOG_INFO,
179fcf3ce44SJohn Forte 		    "MP_GetMultipathLusPlugin()",
180fcf3ce44SJohn Forte 		    " - unable to get OID list.");
181fcf3ce44SJohn Forte 
182fcf3ce44SJohn Forte 		log(LOG_INFO, "MP_GetMultipathLusPlugin()",
183fcf3ce44SJohn Forte 		    " - error exit");
184fcf3ce44SJohn Forte 
185fcf3ce44SJohn Forte 		di_fini(root_node);
186fcf3ce44SJohn Forte 
187fcf3ce44SJohn Forte 		return (MP_STATUS_FAILED);
188fcf3ce44SJohn Forte 	}
189fcf3ce44SJohn Forte 
190fcf3ce44SJohn Forte 	if (0 == numNodes) {
191fcf3ce44SJohn Forte 
192fcf3ce44SJohn Forte 		pOidList = createOidList(1);
193fcf3ce44SJohn Forte 		if (NULL == pOidList) {
194fcf3ce44SJohn Forte 
195fcf3ce44SJohn Forte 			log(LOG_INFO,
196fcf3ce44SJohn Forte 			    "MP_GetMultipathLusPlugin()",
197fcf3ce44SJohn Forte 			    " - unable to create OID list.");
198fcf3ce44SJohn Forte 
199fcf3ce44SJohn Forte 			di_fini(root_node);
200fcf3ce44SJohn Forte 
201fcf3ce44SJohn Forte 			return (MP_STATUS_INSUFFICIENT_MEMORY);
202fcf3ce44SJohn Forte 		}
203fcf3ce44SJohn Forte 
204fcf3ce44SJohn Forte 		pOidList->oids[0].objectType =
2050c3de118SChris Liu 		    MP_OBJECT_TYPE_MULTIPATH_LU;
206fcf3ce44SJohn Forte 
207fcf3ce44SJohn Forte 		pOidList->oids[0].ownerId =
2080c3de118SChris Liu 		    g_pluginOwnerID;
209fcf3ce44SJohn Forte 
210fcf3ce44SJohn Forte 		*ppList = pOidList;
211fcf3ce44SJohn Forte 
212fcf3ce44SJohn Forte 		log(LOG_INFO, "MP_GetMultipathLusPlugin()",
213fcf3ce44SJohn Forte 		    " - returning empty list.");
214fcf3ce44SJohn Forte 
215fcf3ce44SJohn Forte 		di_fini(root_node);
216fcf3ce44SJohn Forte 
217fcf3ce44SJohn Forte 		return (MP_STATUS_SUCCESS);
218fcf3ce44SJohn Forte 	}
219fcf3ce44SJohn Forte 
220fcf3ce44SJohn Forte 	*ppList = createOidList(numNodes);
221fcf3ce44SJohn Forte 	if (NULL == *ppList) {
222fcf3ce44SJohn Forte 		log(LOG_INFO, "MP_GetMultipathLusPlugin()",
223fcf3ce44SJohn Forte 		    "no memory for *ppList");
224fcf3ce44SJohn Forte 		log(LOG_INFO, "MP_GetMultipathLusPlugin()",
225fcf3ce44SJohn Forte 		    " - error exit");
226fcf3ce44SJohn Forte 		return (MP_STATUS_INSUFFICIENT_MEMORY);
227fcf3ce44SJohn Forte 	}
228fcf3ce44SJohn Forte 
229fcf3ce44SJohn Forte 	(*ppList)->oidCount = numNodes;
230fcf3ce44SJohn Forte 
231fcf3ce44SJohn Forte 	numNodes = getOidList(root_node, *ppList);
232fcf3ce44SJohn Forte 
233fcf3ce44SJohn Forte 	for (i = 0; i < (*ppList)->oidCount; i++) {
234fcf3ce44SJohn Forte 
235fcf3ce44SJohn Forte 		log(LOG_INFO, "MP_GetMultipathLusPlugin()",
236fcf3ce44SJohn Forte 		    "(*ppList)->oids[%d].objectType           = %d",
237fcf3ce44SJohn Forte 		    i, (*ppList)->oids[i].objectType);
238fcf3ce44SJohn Forte 		log(LOG_INFO, "MP_GetMultipathLusPlugin()",
239fcf3ce44SJohn Forte 		    "(*ppList)->oids[%d].ownerId              = %d",
240fcf3ce44SJohn Forte 		    i, (*ppList)->oids[i].ownerId);
241fcf3ce44SJohn Forte 		log(LOG_INFO, "MP_GetMultipathLusPlugin()",
242fcf3ce44SJohn Forte 		    "(*ppList)->oids[%d].objectSequenceNumber = %llx",
243fcf3ce44SJohn Forte 		    i, (*ppList)->oids[i].objectSequenceNumber);
244fcf3ce44SJohn Forte 	}
245fcf3ce44SJohn Forte 
246fcf3ce44SJohn Forte 
247fcf3ce44SJohn Forte 	di_fini(root_node);
248fcf3ce44SJohn Forte 
249fcf3ce44SJohn Forte 	log(LOG_INFO, "MP_GetMultipathLusPlugin()", " - exit");
250fcf3ce44SJohn Forte 
251fcf3ce44SJohn Forte 	return (MP_STATUS_SUCCESS);
252fcf3ce44SJohn Forte 
253fcf3ce44SJohn Forte }
254