Skip to content

Commit

Permalink
Merge pull request #92 from iscsi-osx/develop
Browse files Browse the repository at this point in the history
Beta 6
  • Loading branch information
nsinenian committed Jun 3, 2017
2 parents 50d756e + 8620914 commit 1ea61eb
Show file tree
Hide file tree
Showing 12 changed files with 76 additions and 60 deletions.
2 changes: 1 addition & 1 deletion Distribution/package.sh
@@ -1,7 +1,7 @@
# Package parameters
NAME="iSCSI Initiator for macOS"
BUNDLE_ID="com.github.iscsi-osx.iSCSIInitiator"
VERSION="1.0.0-beta5"
VERSION="1.0.0-beta6"

# Output of final DMG
RELEASE="../Release"
Expand Down
2 changes: 1 addition & 1 deletion Source/Kernel/iSCSIHBAUserClient.cpp
Expand Up @@ -1393,7 +1393,7 @@ IOReturn iSCSIHBAUserClient::GetTargetIQNForSessionId(iSCSIHBAUserClient * targe

IOLockUnlock(target->accessLock);

OSSafeRelease(iterator);
OSSafeReleaseNULL(iterator);
return retVal;
}

Expand Down
8 changes: 2 additions & 6 deletions Source/Kernel/iSCSIIOEventSource.cpp
Expand Up @@ -51,11 +51,7 @@ bool iSCSIIOEventSource::init(iSCSIVirtualHBA * owner,

iSCSIIOEventSource::session = session;
iSCSIIOEventSource::connection = connection;

// Initialize task queue to store parallel SCSI tasks for processing
queue_init(&taskQueue);
taskQueueLock = IOSimpleLockAlloc();


return true;
}

Expand Down Expand Up @@ -93,4 +89,4 @@ bool iSCSIIOEventSource::checkForWork()

// Tell workloop thread not to call us again until we signal again...
return false;
}
}
9 changes: 0 additions & 9 deletions Source/Kernel/iSCSIIOEventSource.h
Expand Up @@ -100,15 +100,6 @@ class iSCSIIOEventSource : public IOEventSource
/*! The iSCSI connection associated with this event source. */
iSCSIConnection * connection;

queue_head_t taskQueue;

/*! Flag used to indicate whether the task at the head of the queue is a
* new task that has not yet been processed. */
bool newTask;

/*! Mutex lock used to prevent simultaneous access to the iSCSI task queue
* (e.g., simultaneous calls to addTaskToQueue() and removeTaskFromQueue(). */
IOSimpleLock * taskQueueLock;
};

#endif /* defined(__ISCSI_EVENT_SOURCE_H__) */
6 changes: 0 additions & 6 deletions Source/Kernel/iSCSITaskQueue.cpp
Expand Up @@ -118,12 +118,6 @@ UInt32 iSCSITaskQueue::completeCurrentTask()
return taskTag;
}

/*! Gets the iSCSI task tag of the task that is current being processed.
* @return iSCSI task tag of the current task. */
UInt32 getCurrentTask()
{
return 0;
}

bool iSCSITaskQueue::checkForWork()
{
Expand Down
6 changes: 1 addition & 5 deletions Source/Kernel/iSCSITaskQueue.h
Expand Up @@ -83,10 +83,6 @@ class iSCSITaskQueue : public IOEventSource
/*! Removes all tasks from the queue. */
void clearTasksFromQueue();

/*! Gets the iSCSI task tag of the task that is current being processed.
* @return iSCSI task tag of the current task. */
UInt32 getCurrentTask();

protected:

/*! Called by the attached work loop to check if there is any processing
Expand All @@ -109,4 +105,4 @@ class iSCSITaskQueue : public IOEventSource

};

#endif
#endif
33 changes: 24 additions & 9 deletions Source/Kernel/iSCSIVirtualHBA.cpp
Expand Up @@ -156,9 +156,11 @@ bool iSCSIVirtualHBA::InitializeTargetForID(SCSITargetIdentifier targetId)

if(targetIQN) {
protocolDict->setObject("iSCSI Qualified Name",targetIQN);
device->setProperty(kIOPropertyProtocolCharacteristicsKey,protocolDict);
}

protocolDict->setObject(kIOPropertyPhysicalInterconnectTypeKey,OSString::withCString("iSCSI"));
device->setProperty(kIOPropertyProtocolCharacteristicsKey,protocolDict);

protocolDict->release();
}

Expand Down Expand Up @@ -354,12 +356,13 @@ bool iSCSIVirtualHBA::InitializeController()
SetHBAProperty(kIOPropertyProductNameKey,OSString::withCString(ISCSI_PRODUCT_NAME));
SetHBAProperty(kIOPropertyProductRevisionLevelKey,OSString::withCString(ISCSI_PRODUCT_REVISION_LEVEL));

// Generate an initiator id using a random number (per RFC3720)
kInitiatorId = random();

// Make ourselves discoverable to user clients (we do this last after
// everything is initialized).
registerService();

// Generate an initiator id using a random number (per RFC3720)
kInitiatorId = random();


// Successfully initialized controller
return true;
Expand Down Expand Up @@ -452,8 +455,6 @@ void iSCSIVirtualHBA::HandleConnectionTimeout(SessionIdentifier sessionId,Connec
for(ConnectionIdentifier connectionId = 0; connectionId < kiSCSIMaxConnectionsPerSession; connectionId++)
if(session->connections[connectionId])
connectionCount++;

iSCSIHBAUserClient * client = (iSCSIHBAUserClient*)getClient();

// In the future add recovery here...
if(connectionCount > 1)
Expand All @@ -463,14 +464,17 @@ void iSCSIVirtualHBA::HandleConnectionTimeout(SessionIdentifier sessionId,Connec

// Send a notification to the daemon; if the daemon does not respond then
// release the session or connection as appropriate
if(client->sendTimeoutMessageNotification(sessionId,connectionId) != kIOReturnSuccess)
iSCSIHBAUserClient * client = (iSCSIHBAUserClient*)getClient();

if(client)
client->sendTimeoutMessageNotification(sessionId,connectionId);
else
{
if(connectionCount > 1)
ReleaseConnection(sessionId,connectionId);
else
ReleaseSession(sessionId);
}

}

SCSIServiceResponse iSCSIVirtualHBA::ProcessParallelTask(SCSIParallelTaskIdentifier parallelTask)
Expand Down Expand Up @@ -937,6 +941,7 @@ void iSCSIVirtualHBA::ProcessSCSIResponse(iSCSISession * session,
SetRealizedDataTransferCount(parallelTask,(UInt32)GetRequestedDataTransferCount(parallelTask));

// Process sense data if the PDU came with any...
bool senseDataPresent = false;
if(length >= senseDataHeaderSize)
{
// First two bytes of the data segment are the size of the sense data
Expand All @@ -955,6 +960,8 @@ void iSCSIVirtualHBA::ProcessSCSIResponse(iSCSISession * session,
// Incorporate sense data into the task
SetAutoSenseData(parallelTask,newSenseData,senseDataLength);

senseDataPresent = true;

DBLog("iscsi: Processed sense data (sid: %d, cid: %d)\n",
session->sessionId,connection->cid);
}
Expand All @@ -964,6 +971,13 @@ void iSCSIVirtualHBA::ProcessSCSIResponse(iSCSISession * session,
// know that we're done with this task...

SCSITaskStatus completionStatus = (SCSITaskStatus)bhs->status;

// If sense data has been included along with a check condition response,
// the macOS SCSI stack expects that the task status is "GOOD". Otherwise,
// it queries for auto sense data.
if(completionStatus == kSCSITaskStatus_CHECK_CONDITION && senseDataPresent)
completionStatus = kSCSITaskStatus_GOOD;

SCSIServiceResponse serviceResponse;

if(bhs->response == kiSCSIPDUSCSICmdCompleted)
Expand All @@ -978,6 +992,7 @@ void iSCSIVirtualHBA::ProcessSCSIResponse(iSCSISession * session,

DBLog("iscsi: Processed SCSI response (sid: %d, cid: %d)\n",
session->sessionId,connection->cid);

}

void iSCSIVirtualHBA::ProcessDataIn(iSCSISession * session,
Expand Down Expand Up @@ -1534,7 +1549,7 @@ errno_t iSCSIVirtualHBA::CreateConnection(SessionIdentifier sessionId,
goto EVENTSOURCE_ADD_FAILURE;

newConn->dataRecvEventSource->disable();

// Create a new socket (per RFC3720, only TCP sockets are used.
// Domain can be either IPv4 or IPv6.
error = sock_socket(portalSockaddr->ss_family,
Expand Down
3 changes: 2 additions & 1 deletion Source/User/iSCSI Framework/iSCSIUtils.c
Expand Up @@ -27,6 +27,7 @@
*/

#include "iSCSIUtils.h"
#include <ifaddrs.h>

/*! Minimum TCP port. */
static int PORT_MIN = 0;
Expand All @@ -43,7 +44,7 @@ Boolean iSCSIUtilsValidateIQN(CFStringRef IQN)
{
// IEEE regular expression for matching IQN name
const char pattern[] = "^iqn[.][0-9]{4}-[0-9]{2}[.][[:alnum:]]{1,}[.]"
"[-A-Za-z0-9.]{1,255}:[-A-Za-z0-9.]{1,255}"
"[-A-Za-z0-9.]{1,255}"
"|^eui[.][[:xdigit:]]{16}$";

Boolean validName = false;
Expand Down
3 changes: 2 additions & 1 deletion Source/User/iSCSI Framework/iSCSIUtils.h
Expand Up @@ -33,11 +33,12 @@
#include <IOKit/scsi/SCSICmds_INQUIRY_Definitions.h>

#include <netdb.h>
#include <ifaddrs.h>
#include <regex.h>

#include "iSCSITypes.h"

struct sockaddr_storage;

/*! Verifies whether specified iSCSI qualified name (IQN) is valid per RFC3720.
* This function also validates 64-bit EUI names expressed as strings that
* start with the "eui" prefix.
Expand Down
31 changes: 21 additions & 10 deletions Source/User/iscsid/iSCSIDaemon.c
Expand Up @@ -1643,6 +1643,12 @@ void iSCSIDProcessQueuedLogin(SCNetworkReachabilityRef reachabilityTarget,
* portal when the network becomes available. */
void iSCSIDQueueLogin(iSCSITargetRef target,iSCSIPortalRef portal)
{
if(!target || !portal)
return;

iSCSITargetRetain(target);
iSCSIPortalRetain(portal);

SCNetworkReachabilityRef reachabilityTarget;
SCNetworkReachabilityContext reachabilityContext;

Expand Down Expand Up @@ -1707,10 +1713,6 @@ void iSCSIDSessionTimeoutHandler(iSCSITargetRef target,iSCSIPortalRef portal)
// available
if(iSCSIPreferencesGetPersistenceForTarget(preferences,iSCSITargetGetIQN(target)))
iSCSIDQueueLogin(target,portal);
else {
iSCSITargetRelease(target);
iSCSIPortalRelease(portal);
}
}

/*! Automatically logs in to targets that were specified for auto-login.
Expand All @@ -1731,13 +1733,17 @@ void iSCSIDAutoLogin()
for(CFIndex idx = 0; idx < targetsCount; idx++)
{
CFStringRef targetIQN = CFArrayGetValueAtIndex(targets,idx);
iSCSITargetRef target = iSCSIPreferencesCopyTarget(preferences,targetIQN);
iSCSITargetRef target = NULL;

if(!(target = iSCSIPreferencesCopyTarget(preferences,targetIQN)))
continue;

// See if this target requires auto-login and process it
if(iSCSIPreferencesGetAutoLoginForTarget(preferences,targetIQN)) {

CFArrayRef portals = iSCSIPreferencesCreateArrayOfPortalsForTarget(preferences,targetIQN);
if(!portals)
CFArrayRef portals = NULL;

if(!(portals = iSCSIPreferencesCreateArrayOfPortalsForTarget(preferences,targetIQN)))
continue;

CFIndex portalsCount = CFArrayGetCount(portals);
Expand All @@ -1747,12 +1753,17 @@ void iSCSIDAutoLogin()
{
CFStringRef portalAddress = CFArrayGetValueAtIndex(portals,portalIdx);
iSCSIPortalRef portal = iSCSIPreferencesCopyPortalForTarget(preferences,targetIQN,portalAddress);
iSCSIDQueueLogin(target,portal);

if(portal) {
iSCSIDQueueLogin(target,portal);
iSCSIPortalRelease(portal);
}
}

iSCSITargetRelease(target);
CFRelease(portals);
}

iSCSITargetRelease(target);
}
CFRelease(targets);
}
Expand Down Expand Up @@ -2132,7 +2143,7 @@ int main(void)
discoveryContext.info = &discoveryRecords;
discoveryContext.perform = iSCSIDProcessDiscoveryData;
discoverySource = CFRunLoopSourceCreate(kCFAllocatorDefault,1,&discoveryContext);
CFRunLoopAddSource(CFRunLoopGetMain(),sockSourceRead,kCFRunLoopDefaultMode);
CFRunLoopAddSource(CFRunLoopGetMain(),discoverySource,kCFRunLoopDefaultMode);

asl_log(NULL,NULL,ASL_LEVEL_INFO,"daemon started");

Expand Down
30 changes: 19 additions & 11 deletions Source/User/iscsid/iSCSISession.c
Expand Up @@ -273,6 +273,9 @@ errno_t iSCSINegotiateParseSWDictNormal(iSCSISessionManagerRef managerRef,
// Holds target value & comparison result for keys that we'll process
CFStringRef targetRsp;

// Holds parameters that are used to process other parameters
Boolean initialR2T = false, immediateData = false;

// Get data digest key and compare to requested value
if(CFDictionaryGetValueIfPresent(sessRsp,kRFC3720_Key_MaxConnections,(void*)&targetRsp))
{
Expand All @@ -292,7 +295,7 @@ errno_t iSCSINegotiateParseSWDictNormal(iSCSISessionManagerRef managerRef,
if(CFDictionaryGetValueIfPresent(sessRsp,kRFC3720_Key_InitialR2T,(void*)&targetRsp))
{
CFStringRef initCmd = CFDictionaryGetValue(sessCmd,kRFC3720_Key_InitialR2T);
Boolean initialR2T = iSCSILVGetOr(initCmd,targetRsp);
initialR2T = iSCSILVGetOr(initCmd,targetRsp);
iSCSIHBAInterfaceSetSessionParameter(hbaInterface,sessionId,kiSCSIHBASOInitialR2T,
&initialR2T,sizeof(initialR2T));
}
Expand All @@ -301,7 +304,7 @@ errno_t iSCSINegotiateParseSWDictNormal(iSCSISessionManagerRef managerRef,
if(CFDictionaryGetValueIfPresent(sessRsp,kRFC3720_Key_ImmediateData,(void*)&targetRsp))
{
CFStringRef initCmd = CFDictionaryGetValue(sessCmd,kRFC3720_Key_ImmediateData);
Boolean immediateData = iSCSILVGetAnd(initCmd,targetRsp);
immediateData = iSCSILVGetAnd(initCmd,targetRsp);
iSCSIHBAInterfaceSetSessionParameter(hbaInterface,sessionId,kiSCSIHBASOImmediateData,
&immediateData,sizeof(immediateData));
}
Expand Down Expand Up @@ -336,16 +339,20 @@ errno_t iSCSINegotiateParseSWDictNormal(iSCSISessionManagerRef managerRef,
// Grab minimum of first burst length
if(CFDictionaryGetValueIfPresent(sessRsp,kRFC3720_Key_FirstBurstLength,(void*)&targetRsp))
{
CFStringRef initCmd = CFDictionaryGetValue(sessCmd,kRFC3720_Key_FirstBurstLength);
UInt32 firstBurstLength = CFStringGetIntValue(targetRsp);
// This parameter is irrelevant when initialR2T = yes and immediateData = no.
if(!initialR2T || immediateData) {

// Range-check value...
if(iSCSILVRangeInvalid(firstBurstLength,kRFC3720_FirstBurstLength_Min,kRFC3720_FirstBurstLength_Max))
return ENOTSUP;
CFStringRef initCmd = CFDictionaryGetValue(sessCmd,kRFC3720_Key_FirstBurstLength);
UInt32 firstBurstLength = CFStringGetIntValue(targetRsp);

firstBurstLength = iSCSILVGetMin(initCmd,targetRsp);
iSCSIHBAInterfaceSetSessionParameter(hbaInterface,sessionId,kiSCSIHBASOFirstBurstLength,
&firstBurstLength,sizeof(firstBurstLength));
// Range-check value...
if(iSCSILVRangeInvalid(firstBurstLength,kRFC3720_FirstBurstLength_Min,kRFC3720_FirstBurstLength_Max))
return ENOTSUP;

firstBurstLength = iSCSILVGetMin(initCmd,targetRsp);
iSCSIHBAInterfaceSetSessionParameter(hbaInterface,sessionId,kiSCSIHBASOFirstBurstLength,
&firstBurstLength,sizeof(firstBurstLength));
}
}

// Grab minimum of max outstanding R2T
Expand Down Expand Up @@ -499,7 +506,8 @@ errno_t iSCSINegotiateSession(iSCSISessionManagerRef managerRef,
iSCSINegotiateBuildSWDictCommon(sessCfg,sessCmd);

// If target name is specified, this is a normal session; add parameters
if(iSCSITargetGetIQN(target) != NULL)
Boolean discoverySession = CFStringCompare(iSCSITargetGetIQN(target),kiSCSIUnspecifiedTargetIQN,0) == kCFCompareEqualTo;
if(!discoverySession)
iSCSINegotiateBuildSWDictNormal(sessCfg,sessCmd);

// Add connection parameters
Expand Down
3 changes: 3 additions & 0 deletions Source/User/iscsid/iSCSISessionManager.c
Expand Up @@ -66,6 +66,9 @@ struct __iSCSISessionManager
// Call user-defined callback function if one exists
if(managerRef->callbacks.timeoutCallback)
managerRef->callbacks.timeoutCallback(target,portal);

iSCSITargetRelease(target);
iSCSIPortalRelease(portal);
}

/*! Called to handle asynchronous events that involve dropped sessions, connections,
Expand Down

0 comments on commit 1ea61eb

Please sign in to comment.