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