xref: /illumos-gate/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetMultipathLusPlugin.c (revision 89b2a9fbeabf42fa54594df0e5927bcc50a07cc9)
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 <syslog.h>
27 #include <errno.h>
28 #include <unistd.h>
29 #include <stropts.h>
30 
31 #include "mp_utils.h"
32 
33 #include <libdevinfo.h>
34 
35 /*
36  * Checks whether there is online path or not.
37  *  - no path found returns -1.
38  *  - online/standby path found returns 1.
39  *  - path exists but no online/standby path found returns 0.
40  */
41 static int checkAvailablePath(di_node_t node)
42 {
43 	di_path_t path;
44 	di_path_state_t state;
45 
46 	if ((path = di_path_client_next_path(node, DI_PATH_NIL))
47 	    == DI_PATH_NIL) {
48 		log(LOG_INFO, "checkAvailalblePath()",
49 		    " - No path found");
50 		return (-1);
51 	}
52 
53 	do {
54 		/* ignore the path that is neither online nor standby. */
55 		if (((state = di_path_state(path)) == DI_PATH_STATE_ONLINE) ||
56 		    (state == DI_PATH_STATE_STANDBY)) {
57 			return (1);
58 		}
59 	} while ((path = di_path_client_next_path(node, path)) != DI_PATH_NIL);
60 
61 	/* return 0 for the case that there is no online path to the node. */
62 	log(LOG_INFO, "checkAvailalblePath()", " - No online path found");
63 	return (0);
64 }
65 
66 static int getOidList(di_node_t root_node, MP_OID_LIST *pOidList)
67 {
68 	int numNodes = 0, state;
69 
70 	MP_UINT64 instNum = 0;
71 
72 	di_node_t sv_node	= DI_NODE_NIL;
73 	di_node_t sv_child_node = DI_NODE_NIL;
74 
75 	int haveList = (NULL != pOidList);
76 
77 
78 	log(LOG_INFO, "getOidList()", " - enter");
79 
80 
81 	sv_node = di_drv_first_node("scsi_vhci", root_node);
82 	if (DI_NODE_NIL == sv_node) {
83 		log(LOG_INFO, "getOidList()",
84 		    " - di_drv_first_node() failed");
85 
86 		return (-1);
87 	}
88 
89 	sv_child_node = di_child_node(sv_node);
90 
91 	while (DI_NODE_NIL != sv_child_node) {
92 
93 		/* skip the node which is offline, down or detached. */
94 		state = di_state(sv_child_node);
95 		if ((state & DI_DEVICE_DOWN) ||
96 		    (state & DI_DEVICE_OFFLINE)) {
97 			sv_child_node = di_sibling_node(sv_child_node);
98 			continue;
99 		}
100 
101 		/*
102 		 * skip if the node doesn't have any path avaialble.
103 		 * If any path is found from the DINFOCACHE snaphost
104 		 * that means the driver keeps track of the path regadless
105 		 * of state.
106 		 */
107 		if (checkAvailablePath(sv_child_node) == -1) {
108 			sv_child_node = di_sibling_node(sv_child_node);
109 			continue;
110 		}
111 
112 		if (haveList && (numNodes < pOidList->oidCount)) {
113 
114 			instNum =
115 			    (MP_UINT64)di_instance(sv_child_node);
116 
117 			log(LOG_INFO, "getOidList()",
118 			    " - instance number is: %llx",
119 			    instNum);
120 
121 			pOidList->oids[numNodes].objectType =
122 			    MP_OBJECT_TYPE_MULTIPATH_LU;
123 
124 			pOidList->oids[numNodes].ownerId =
125 			    g_pluginOwnerID;
126 
127 			pOidList->oids[numNodes].objectSequenceNumber =
128 			    instNum;
129 		}
130 
131 		++numNodes;
132 
133 		sv_child_node = di_sibling_node(sv_child_node);
134 	}
135 
136 	log(LOG_INFO,
137 	    "getOidList()",
138 	    " - numNodes: %d",
139 	    numNodes);
140 
141 
142 
143 	log(LOG_INFO, "getOidList()", " - exit");
144 
145 	return (numNodes);
146 }
147 
148 
149 MP_STATUS
150 MP_GetMultipathLusPlugin(MP_OID_LIST **ppList)
151 {
152 	di_node_t root_node	= DI_NODE_NIL;
153 	MP_OID_LIST *pOidList   = NULL;
154 
155 	int numNodes = 0;
156 	int i = 0;
157 
158 	log(LOG_INFO, "MP_GetMultipathLusPlugin()", " - enter");
159 
160 
161 	root_node = di_init("/", DINFOCACHE);
162 	if (DI_NODE_NIL == root_node) {
163 		log(LOG_INFO, "MP_GetMultipathLusPlugin()",
164 		    " - di_init() failed");
165 
166 		return (MP_STATUS_FAILED);
167 	}
168 
169 	numNodes = getOidList(root_node, NULL);
170 
171 	if (numNodes < 0) {
172 
173 		log(LOG_INFO,
174 		    "MP_GetMultipathLusPlugin()",
175 		    " - unable to get OID list.");
176 
177 		log(LOG_INFO, "MP_GetMultipathLusPlugin()",
178 		    " - error exit");
179 
180 		di_fini(root_node);
181 
182 		return (MP_STATUS_FAILED);
183 	}
184 
185 	if (0 == numNodes) {
186 
187 		pOidList = createOidList(1);
188 		if (NULL == pOidList) {
189 
190 			log(LOG_INFO,
191 			    "MP_GetMultipathLusPlugin()",
192 			    " - unable to create OID list.");
193 
194 			di_fini(root_node);
195 
196 			return (MP_STATUS_INSUFFICIENT_MEMORY);
197 		}
198 
199 		pOidList->oids[0].objectType =
200 		    MP_OBJECT_TYPE_MULTIPATH_LU;
201 
202 		pOidList->oids[0].ownerId =
203 		    g_pluginOwnerID;
204 
205 		*ppList = pOidList;
206 
207 		log(LOG_INFO, "MP_GetMultipathLusPlugin()",
208 		    " - returning empty list.");
209 
210 		di_fini(root_node);
211 
212 		return (MP_STATUS_SUCCESS);
213 	}
214 
215 	*ppList = createOidList(numNodes);
216 	if (NULL == *ppList) {
217 		log(LOG_INFO, "MP_GetMultipathLusPlugin()",
218 		    "no memory for *ppList");
219 		log(LOG_INFO, "MP_GetMultipathLusPlugin()",
220 		    " - error exit");
221 		return (MP_STATUS_INSUFFICIENT_MEMORY);
222 	}
223 
224 	(*ppList)->oidCount = numNodes;
225 
226 	numNodes = getOidList(root_node, *ppList);
227 
228 	for (i = 0; i < (*ppList)->oidCount; i++) {
229 
230 		log(LOG_INFO, "MP_GetMultipathLusPlugin()",
231 		    "(*ppList)->oids[%d].objectType           = %d",
232 		    i, (*ppList)->oids[i].objectType);
233 		log(LOG_INFO, "MP_GetMultipathLusPlugin()",
234 		    "(*ppList)->oids[%d].ownerId              = %d",
235 		    i, (*ppList)->oids[i].ownerId);
236 		log(LOG_INFO, "MP_GetMultipathLusPlugin()",
237 		    "(*ppList)->oids[%d].objectSequenceNumber = %llx",
238 		    i, (*ppList)->oids[i].objectSequenceNumber);
239 	}
240 
241 
242 	di_fini(root_node);
243 
244 	log(LOG_INFO, "MP_GetMultipathLusPlugin()", " - exit");
245 
246 	return (MP_STATUS_SUCCESS);
247 
248 }
249