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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 27 28 #include "HandlePort.h" 29 #include "Exceptions.h" 30 #include "Trace.h" 31 #include <iostream> 32 #include <iomanip> 33 #include <sys/types.h> 34 #include <sys/stat.h> 35 #include <fcntl.h> 36 #include <unistd.h> 37 #include <stropts.h> 38 39 40 using namespace std; 41 42 /** 43 * @memo Construct a new HandlePort for state tracking 44 * @precondition Handle must be open 45 * @param myHandle The open handle for this HBA 46 * @param myHBA The HBA for this port 47 * @param myPort The HBA Port to open 48 */ 49 HandlePort::HandlePort(Handle *myHandle, HBA *myHBA, HBAPort *myPort) : 50 handle(myHandle), hba(myHBA), port(myPort), active(false) { 51 Trace log("HandlePort::HandlePort"); 52 } 53 54 /** 55 * @memo Reset the state tracking values for stale index detection 56 * @postcondition The first subsequent call to any index based routine 57 * will always succed. 58 */ 59 void HandlePort::refresh() { 60 Trace log("HandlePort::refresh"); 61 lock(); 62 active = false; 63 unlock(); 64 } 65 66 /** 67 * @memo Validate the current state of the handle port 68 * @exception StaleDataException Thrown if the state has changed 69 * @param newState The new state of the port 70 * 71 * @doc After opening a port or refreshing, no state is tracked. 72 * The first time validate is called, the state is recorded. 73 * Subsequent calls will verify that the state is the same. 74 * If the state has changed, the exception will be thrown. 75 */ 76 void HandlePort::validate(uint64_t newState) { 77 Trace log("HandlePort::validate"); 78 log.debug("Port %016llx state %016llx", port->getPortWWN(), newState); 79 lock(); 80 if (active) { 81 if (lastState != newState) { 82 unlock(); 83 throw StaleDataException(); 84 } 85 } else { 86 active = true; 87 lastState = newState; 88 } 89 unlock(); 90 } 91 92 /** 93 * @memo Verify this port has the stated port wwn 94 * @return TRUE if the argument matches this port 95 * @return FALSE if the argument does not match this port 96 * @param portWWN The Port WWN to compare against this port 97 */ 98 bool HandlePort::match(uint64_t portWWN) { 99 Trace log("HandlePort::match(wwn)"); 100 bool ret = false; 101 ret = (portWWN == port->getPortWWN()); 102 return (ret); 103 } 104 105 /** 106 * @memo Verify this port is the stated index 107 * @return TRUE if the argument matches this port 108 * @return FALSE if the argument does not match this port 109 * @param index The index value to compare against this port 110 */ 111 bool HandlePort::match(int index) { 112 Trace log("HandlePort::match(index)"); 113 return (*port == *(hba->getPortByIndex(index))); 114 } 115 116 /** 117 * @memo Get attributes from a discovered port. 118 * @exception ... underlying exceptions will be thrown 119 * @return The discovered port attributes 120 * @param wwn The node or port wwn of the discovered port 121 * 122 * @doc This routine will not perform any state validation 123 */ 124 HBA_PORTATTRIBUTES HandlePort::getDiscoveredAttributes(uint64_t wwn) { 125 Trace log("HandlePort::getDiscoveredAttributes(wwn)"); 126 uint64_t newState; 127 HBA_PORTATTRIBUTES attributes = port->getDiscoveredAttributes( 128 wwn, newState); 129 // We don't validate when a WWN was used 130 return (attributes); 131 } 132 133 /** 134 * @memo Get attributes from this port. 135 * @exception ... underlying exceptions will be thrown 136 * @return The port attributes 137 * @see HandlePort::validate 138 * 139 * @doc This routine will perform state validation 140 */ 141 HBA_PORTATTRIBUTES HandlePort::getPortAttributes() { 142 Trace log("HandlePort::getPortAttributes"); 143 uint64_t newState; 144 HBA_PORTATTRIBUTES attributes = port->getPortAttributes(newState); 145 validate(newState); 146 return (attributes); 147 } 148 149 /** 150 * @memo Get attributes from a discovered port. 151 * @exception ... underlying exceptions will be thrown 152 * @return The discovered port attributes 153 * @param discoveredport The index of the discovered port 154 * @see HandlePort::validate 155 * 156 * @doc This routine will perform state validation 157 */ 158 HBA_PORTATTRIBUTES 159 HandlePort::getDiscoveredAttributes(HBA_UINT32 discoveredport) { 160 Trace log("HandlePort::getDiscoveredAttributes(index)"); 161 uint64_t newState; 162 HBA_PORTATTRIBUTES attributes = port->getDiscoveredAttributes( 163 discoveredport, newState); 164 validate(newState); 165 return (attributes); 166 } 167 168 HBA_PORTNPIVATTRIBUTES HandlePort::getPortNPIVAttributes() { 169 Trace log("HandlePort::getPortNPIVAttributes"); 170 uint64_t newState; 171 HBA_PORTNPIVATTRIBUTES attributes = port->getPortNPIVAttributes(newState); 172 validate(newState); 173 return (attributes); 174 } 175 176 uint32_t HandlePort::deleteNPIVPort(uint64_t vportwwn) { 177 Trace log("HandlePort::deleteNPIVPort"); 178 uint32_t ret = port->deleteNPIVPort(vportwwn); 179 180 return (ret); 181 } 182 183 uint32_t HandlePort::createNPIVPort(uint64_t vnodewwn, 184 uint64_t vportwwn, uint32_t vindex) { 185 Trace log("HandlePort::createNPIVPort"); 186 uint32_t vportindex; 187 188 vportindex = port->createNPIVPort(vnodewwn, vportwwn, vindex); 189 return (vportindex); 190 } 191 192 HandleNPIVPort* HandlePort::getHandleNPIVPortByIndex(int index) { 193 Trace log("HandlePort::getHandleNPIVPortByIndex(int index)"); 194 195 HBANPIVPort* vport = port->getPortByIndex(index); 196 return (getHandleNPIVPort(vport->getPortWWN())); 197 } 198 199 HandleNPIVPort* HandlePort::getHandleNPIVPort(uint64_t wwn) { 200 Trace log("HandlePort::getHandleNPIVPort"); 201 lock(); 202 try { 203 // Check to see if the wwn is in the map 204 if (npivportHandles.find(wwn) == npivportHandles.end()) { 205 // Not found, add a new one 206 HBANPIVPort* vport = port->getPort(wwn); 207 npivportHandles[wwn] = new HandleNPIVPort(handle, this, hba, port, vport); 208 } 209 HandleNPIVPort *npivportHandle = npivportHandles[wwn]; 210 unlock(); 211 return (npivportHandle); 212 } catch (...) { 213 unlock(); 214 throw; 215 } 216 } 217 218