17836SJohn.Forte@Sun.COM /*
27836SJohn.Forte@Sun.COM  * CDDL HEADER START
37836SJohn.Forte@Sun.COM  *
47836SJohn.Forte@Sun.COM  * The contents of this file are subject to the terms of the
57836SJohn.Forte@Sun.COM  * Common Development and Distribution License (the "License").
67836SJohn.Forte@Sun.COM  * You may not use this file except in compliance with the License.
77836SJohn.Forte@Sun.COM  *
87836SJohn.Forte@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97836SJohn.Forte@Sun.COM  * or http://www.opensolaris.org/os/licensing.
107836SJohn.Forte@Sun.COM  * See the License for the specific language governing permissions
117836SJohn.Forte@Sun.COM  * and limitations under the License.
127836SJohn.Forte@Sun.COM  *
137836SJohn.Forte@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
147836SJohn.Forte@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157836SJohn.Forte@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
167836SJohn.Forte@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
177836SJohn.Forte@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
187836SJohn.Forte@Sun.COM  *
197836SJohn.Forte@Sun.COM  * CDDL HEADER END
207836SJohn.Forte@Sun.COM  */
217836SJohn.Forte@Sun.COM /*
22*12334SJiri.Svoboda@Sun.COM  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
237836SJohn.Forte@Sun.COM  */
247836SJohn.Forte@Sun.COM 
257836SJohn.Forte@Sun.COM #include <syslog.h>
267836SJohn.Forte@Sun.COM #include <errno.h>
277836SJohn.Forte@Sun.COM #include <unistd.h>
287836SJohn.Forte@Sun.COM #include <stropts.h>
297836SJohn.Forte@Sun.COM 
307836SJohn.Forte@Sun.COM #include "mp_utils.h"
317836SJohn.Forte@Sun.COM 
327836SJohn.Forte@Sun.COM #include <libdevinfo.h>
337836SJohn.Forte@Sun.COM 
3410696SDavid.Hollister@Sun.COM /*
3510696SDavid.Hollister@Sun.COM  * Checks whether there is online path or not.
3610696SDavid.Hollister@Sun.COM  *  - no path found returns -1.
3710696SDavid.Hollister@Sun.COM  *  - online/standby path found returns 1.
3810696SDavid.Hollister@Sun.COM  *  - path exists but no online/standby path found returns 0.
3910696SDavid.Hollister@Sun.COM  */
checkAvailablePath(di_node_t node)4010696SDavid.Hollister@Sun.COM static int checkAvailablePath(di_node_t node)
4110696SDavid.Hollister@Sun.COM {
4210696SDavid.Hollister@Sun.COM 	di_path_t path;
4310696SDavid.Hollister@Sun.COM 	di_path_state_t state;
4410696SDavid.Hollister@Sun.COM 
4510696SDavid.Hollister@Sun.COM 	if ((path = di_path_client_next_path(node, DI_PATH_NIL))
4610696SDavid.Hollister@Sun.COM 	    == DI_PATH_NIL) {
4710696SDavid.Hollister@Sun.COM 		log(LOG_INFO, "checkAvailalblePath()",
4810696SDavid.Hollister@Sun.COM 		    " - No path found");
4910696SDavid.Hollister@Sun.COM 		return (-1);
5010696SDavid.Hollister@Sun.COM 	}
5110696SDavid.Hollister@Sun.COM 
5210696SDavid.Hollister@Sun.COM 	do {
5310696SDavid.Hollister@Sun.COM 		/* ignore the path that is neither online nor standby. */
5410696SDavid.Hollister@Sun.COM 		if (((state = di_path_state(path)) == DI_PATH_STATE_ONLINE) ||
5510696SDavid.Hollister@Sun.COM 		    (state == DI_PATH_STATE_STANDBY)) {
5610696SDavid.Hollister@Sun.COM 			return (1);
5710696SDavid.Hollister@Sun.COM 		}
5810696SDavid.Hollister@Sun.COM 	} while ((path = di_path_client_next_path(node, path)) != DI_PATH_NIL);
5910696SDavid.Hollister@Sun.COM 
6010696SDavid.Hollister@Sun.COM 	/* return 0 for the case that there is no online path to the node. */
6110696SDavid.Hollister@Sun.COM 	log(LOG_INFO, "checkAvailalblePath()", " - No online path found");
6210696SDavid.Hollister@Sun.COM 	return (0);
6310696SDavid.Hollister@Sun.COM }
6410696SDavid.Hollister@Sun.COM 
getOidList(di_node_t root_node,MP_OID_LIST * pOidList)657836SJohn.Forte@Sun.COM static int getOidList(di_node_t root_node, MP_OID_LIST *pOidList)
667836SJohn.Forte@Sun.COM {
6710696SDavid.Hollister@Sun.COM 	int numNodes = 0, state;
687836SJohn.Forte@Sun.COM 
69*12334SJiri.Svoboda@Sun.COM 	int instNum;
70*12334SJiri.Svoboda@Sun.COM 	int majorNum;
71*12334SJiri.Svoboda@Sun.COM 	MP_UINT64 osn;
727836SJohn.Forte@Sun.COM 
737836SJohn.Forte@Sun.COM 	di_node_t sv_node	= DI_NODE_NIL;
747836SJohn.Forte@Sun.COM 	di_node_t sv_child_node = DI_NODE_NIL;
757836SJohn.Forte@Sun.COM 
767836SJohn.Forte@Sun.COM 	int haveList = (NULL != pOidList);
777836SJohn.Forte@Sun.COM 
787836SJohn.Forte@Sun.COM 
797836SJohn.Forte@Sun.COM 	log(LOG_INFO, "getOidList()", " - enter");
807836SJohn.Forte@Sun.COM 
817836SJohn.Forte@Sun.COM 
827836SJohn.Forte@Sun.COM 	sv_node = di_drv_first_node("scsi_vhci", root_node);
837836SJohn.Forte@Sun.COM 	if (DI_NODE_NIL == sv_node) {
847836SJohn.Forte@Sun.COM 		log(LOG_INFO, "getOidList()",
857836SJohn.Forte@Sun.COM 		    " - di_drv_first_node() failed");
867836SJohn.Forte@Sun.COM 
877836SJohn.Forte@Sun.COM 		return (-1);
887836SJohn.Forte@Sun.COM 	}
897836SJohn.Forte@Sun.COM 
907836SJohn.Forte@Sun.COM 	sv_child_node = di_child_node(sv_node);
917836SJohn.Forte@Sun.COM 
927836SJohn.Forte@Sun.COM 	while (DI_NODE_NIL != sv_child_node) {
937836SJohn.Forte@Sun.COM 
9410696SDavid.Hollister@Sun.COM 		/* skip the node which is offline, down or detached. */
9510696SDavid.Hollister@Sun.COM 		state = di_state(sv_child_node);
9610696SDavid.Hollister@Sun.COM 		if ((state & DI_DEVICE_DOWN) ||
9710696SDavid.Hollister@Sun.COM 		    (state & DI_DEVICE_OFFLINE)) {
9810696SDavid.Hollister@Sun.COM 			sv_child_node = di_sibling_node(sv_child_node);
9910696SDavid.Hollister@Sun.COM 			continue;
10010696SDavid.Hollister@Sun.COM 		}
10110696SDavid.Hollister@Sun.COM 
10210696SDavid.Hollister@Sun.COM 		/*
10310696SDavid.Hollister@Sun.COM 		 * skip if the node doesn't have any path avaialble.
10410696SDavid.Hollister@Sun.COM 		 * If any path is found from the DINFOCACHE snaphost
10510696SDavid.Hollister@Sun.COM 		 * that means the driver keeps track of the path regadless
10610696SDavid.Hollister@Sun.COM 		 * of state.
10710696SDavid.Hollister@Sun.COM 		 */
10810696SDavid.Hollister@Sun.COM 		if (checkAvailablePath(sv_child_node) == -1) {
10910486SJiri.Svoboda@Sun.COM 			sv_child_node = di_sibling_node(sv_child_node);
11010486SJiri.Svoboda@Sun.COM 			continue;
11110486SJiri.Svoboda@Sun.COM 		}
1127836SJohn.Forte@Sun.COM 
11310486SJiri.Svoboda@Sun.COM 		if (haveList && (numNodes < pOidList->oidCount)) {
114*12334SJiri.Svoboda@Sun.COM 			instNum = di_instance(sv_child_node);
115*12334SJiri.Svoboda@Sun.COM 			majorNum = di_driver_major(sv_child_node);
1167836SJohn.Forte@Sun.COM 
1177836SJohn.Forte@Sun.COM 			log(LOG_INFO, "getOidList()",
118*12334SJiri.Svoboda@Sun.COM 			    "instNum = %d", instNum);
119*12334SJiri.Svoboda@Sun.COM 			log(LOG_INFO, "getOidList()",
120*12334SJiri.Svoboda@Sun.COM 			    "majorNum = %d", majorNum);
121*12334SJiri.Svoboda@Sun.COM 
122*12334SJiri.Svoboda@Sun.COM 			osn = 0;
123*12334SJiri.Svoboda@Sun.COM 			osn = MP_STORE_INST_TO_ID(instNum, osn);
124*12334SJiri.Svoboda@Sun.COM 			osn = MP_STORE_MAJOR_TO_ID(majorNum, osn);
1257836SJohn.Forte@Sun.COM 
1267836SJohn.Forte@Sun.COM 			pOidList->oids[numNodes].objectType =
1279782SChris.Liu@Sun.COM 			    MP_OBJECT_TYPE_MULTIPATH_LU;
1287836SJohn.Forte@Sun.COM 
1297836SJohn.Forte@Sun.COM 			pOidList->oids[numNodes].ownerId =
1309782SChris.Liu@Sun.COM 			    g_pluginOwnerID;
1317836SJohn.Forte@Sun.COM 
1327836SJohn.Forte@Sun.COM 			pOidList->oids[numNodes].objectSequenceNumber =
133*12334SJiri.Svoboda@Sun.COM 			    osn;
1347836SJohn.Forte@Sun.COM 		}
1357836SJohn.Forte@Sun.COM 
1367836SJohn.Forte@Sun.COM 		++numNodes;
1377836SJohn.Forte@Sun.COM 
1387836SJohn.Forte@Sun.COM 		sv_child_node = di_sibling_node(sv_child_node);
1397836SJohn.Forte@Sun.COM 	}
1407836SJohn.Forte@Sun.COM 
1417836SJohn.Forte@Sun.COM 	log(LOG_INFO,
1427836SJohn.Forte@Sun.COM 	    "getOidList()",
1437836SJohn.Forte@Sun.COM 	    " - numNodes: %d",
1447836SJohn.Forte@Sun.COM 	    numNodes);
1457836SJohn.Forte@Sun.COM 
1467836SJohn.Forte@Sun.COM 
1477836SJohn.Forte@Sun.COM 
1487836SJohn.Forte@Sun.COM 	log(LOG_INFO, "getOidList()", " - exit");
1497836SJohn.Forte@Sun.COM 
1507836SJohn.Forte@Sun.COM 	return (numNodes);
1517836SJohn.Forte@Sun.COM }
1527836SJohn.Forte@Sun.COM 
1537836SJohn.Forte@Sun.COM 
1547836SJohn.Forte@Sun.COM MP_STATUS
MP_GetMultipathLusPlugin(MP_OID_LIST ** ppList)1557836SJohn.Forte@Sun.COM MP_GetMultipathLusPlugin(MP_OID_LIST **ppList)
1567836SJohn.Forte@Sun.COM {
1577836SJohn.Forte@Sun.COM 	di_node_t root_node	= DI_NODE_NIL;
1587836SJohn.Forte@Sun.COM 	MP_OID_LIST *pOidList   = NULL;
1597836SJohn.Forte@Sun.COM 
1607836SJohn.Forte@Sun.COM 	int numNodes = 0;
1617836SJohn.Forte@Sun.COM 	int i = 0;
1627836SJohn.Forte@Sun.COM 
1637836SJohn.Forte@Sun.COM 	log(LOG_INFO, "MP_GetMultipathLusPlugin()", " - enter");
1647836SJohn.Forte@Sun.COM 
1657836SJohn.Forte@Sun.COM 
1667836SJohn.Forte@Sun.COM 	root_node = di_init("/", DINFOCACHE);
1677836SJohn.Forte@Sun.COM 	if (DI_NODE_NIL == root_node) {
1687836SJohn.Forte@Sun.COM 		log(LOG_INFO, "MP_GetMultipathLusPlugin()",
1697836SJohn.Forte@Sun.COM 		    " - di_init() failed");
1707836SJohn.Forte@Sun.COM 
1717836SJohn.Forte@Sun.COM 		return (MP_STATUS_FAILED);
1727836SJohn.Forte@Sun.COM 	}
1737836SJohn.Forte@Sun.COM 
1747836SJohn.Forte@Sun.COM 	numNodes = getOidList(root_node, NULL);
1757836SJohn.Forte@Sun.COM 
1767836SJohn.Forte@Sun.COM 	if (numNodes < 0) {
1777836SJohn.Forte@Sun.COM 
1787836SJohn.Forte@Sun.COM 		log(LOG_INFO,
1797836SJohn.Forte@Sun.COM 		    "MP_GetMultipathLusPlugin()",
1807836SJohn.Forte@Sun.COM 		    " - unable to get OID list.");
1817836SJohn.Forte@Sun.COM 
1827836SJohn.Forte@Sun.COM 		log(LOG_INFO, "MP_GetMultipathLusPlugin()",
1837836SJohn.Forte@Sun.COM 		    " - error exit");
1847836SJohn.Forte@Sun.COM 
1857836SJohn.Forte@Sun.COM 		di_fini(root_node);
1867836SJohn.Forte@Sun.COM 
1877836SJohn.Forte@Sun.COM 		return (MP_STATUS_FAILED);
1887836SJohn.Forte@Sun.COM 	}
1897836SJohn.Forte@Sun.COM 
1907836SJohn.Forte@Sun.COM 	if (0 == numNodes) {
1917836SJohn.Forte@Sun.COM 
1927836SJohn.Forte@Sun.COM 		pOidList = createOidList(1);
1937836SJohn.Forte@Sun.COM 		if (NULL == pOidList) {
1947836SJohn.Forte@Sun.COM 
1957836SJohn.Forte@Sun.COM 			log(LOG_INFO,
1967836SJohn.Forte@Sun.COM 			    "MP_GetMultipathLusPlugin()",
1977836SJohn.Forte@Sun.COM 			    " - unable to create OID list.");
1987836SJohn.Forte@Sun.COM 
1997836SJohn.Forte@Sun.COM 			di_fini(root_node);
2007836SJohn.Forte@Sun.COM 
2017836SJohn.Forte@Sun.COM 			return (MP_STATUS_INSUFFICIENT_MEMORY);
2027836SJohn.Forte@Sun.COM 		}
2037836SJohn.Forte@Sun.COM 
2047836SJohn.Forte@Sun.COM 		pOidList->oids[0].objectType =
2059782SChris.Liu@Sun.COM 		    MP_OBJECT_TYPE_MULTIPATH_LU;
2067836SJohn.Forte@Sun.COM 
2077836SJohn.Forte@Sun.COM 		pOidList->oids[0].ownerId =
2089782SChris.Liu@Sun.COM 		    g_pluginOwnerID;
2097836SJohn.Forte@Sun.COM 
2107836SJohn.Forte@Sun.COM 		*ppList = pOidList;
2117836SJohn.Forte@Sun.COM 
2127836SJohn.Forte@Sun.COM 		log(LOG_INFO, "MP_GetMultipathLusPlugin()",
2137836SJohn.Forte@Sun.COM 		    " - returning empty list.");
2147836SJohn.Forte@Sun.COM 
2157836SJohn.Forte@Sun.COM 		di_fini(root_node);
2167836SJohn.Forte@Sun.COM 
2177836SJohn.Forte@Sun.COM 		return (MP_STATUS_SUCCESS);
2187836SJohn.Forte@Sun.COM 	}
2197836SJohn.Forte@Sun.COM 
2207836SJohn.Forte@Sun.COM 	*ppList = createOidList(numNodes);
2217836SJohn.Forte@Sun.COM 	if (NULL == *ppList) {
2227836SJohn.Forte@Sun.COM 		log(LOG_INFO, "MP_GetMultipathLusPlugin()",
2237836SJohn.Forte@Sun.COM 		    "no memory for *ppList");
2247836SJohn.Forte@Sun.COM 		log(LOG_INFO, "MP_GetMultipathLusPlugin()",
2257836SJohn.Forte@Sun.COM 		    " - error exit");
2267836SJohn.Forte@Sun.COM 		return (MP_STATUS_INSUFFICIENT_MEMORY);
2277836SJohn.Forte@Sun.COM 	}
2287836SJohn.Forte@Sun.COM 
2297836SJohn.Forte@Sun.COM 	(*ppList)->oidCount = numNodes;
2307836SJohn.Forte@Sun.COM 
2317836SJohn.Forte@Sun.COM 	numNodes = getOidList(root_node, *ppList);
2327836SJohn.Forte@Sun.COM 
2337836SJohn.Forte@Sun.COM 	for (i = 0; i < (*ppList)->oidCount; i++) {
2347836SJohn.Forte@Sun.COM 
2357836SJohn.Forte@Sun.COM 		log(LOG_INFO, "MP_GetMultipathLusPlugin()",
2367836SJohn.Forte@Sun.COM 		    "(*ppList)->oids[%d].objectType           = %d",
2377836SJohn.Forte@Sun.COM 		    i, (*ppList)->oids[i].objectType);
2387836SJohn.Forte@Sun.COM 		log(LOG_INFO, "MP_GetMultipathLusPlugin()",
2397836SJohn.Forte@Sun.COM 		    "(*ppList)->oids[%d].ownerId              = %d",
2407836SJohn.Forte@Sun.COM 		    i, (*ppList)->oids[i].ownerId);
2417836SJohn.Forte@Sun.COM 		log(LOG_INFO, "MP_GetMultipathLusPlugin()",
2427836SJohn.Forte@Sun.COM 		    "(*ppList)->oids[%d].objectSequenceNumber = %llx",
2437836SJohn.Forte@Sun.COM 		    i, (*ppList)->oids[i].objectSequenceNumber);
2447836SJohn.Forte@Sun.COM 	}
2457836SJohn.Forte@Sun.COM 
2467836SJohn.Forte@Sun.COM 
2477836SJohn.Forte@Sun.COM 	di_fini(root_node);
2487836SJohn.Forte@Sun.COM 
2497836SJohn.Forte@Sun.COM 	log(LOG_INFO, "MP_GetMultipathLusPlugin()", " - exit");
2507836SJohn.Forte@Sun.COM 
2517836SJohn.Forte@Sun.COM 	return (MP_STATUS_SUCCESS);
2527836SJohn.Forte@Sun.COM 
2537836SJohn.Forte@Sun.COM }
254