Sfoglia il codice sorgente

Minor code cleanup

the code for executing the SCSICommand and preparing the response has
been moved to a separate method
Tal Aloni 8 anni fa
parent
commit
5b20fc8b1f
2 ha cambiato i file con 85 aggiunte e 67 eliminazioni
  1. 23 12
      ISCSI/Server/ISCSIServer.cs
  2. 62 55
      ISCSI/Server/TargetResponseHelper.cs

+ 23 - 12
ISCSI/Server/ISCSIServer.cs

@@ -456,21 +456,32 @@ namespace ISCSI.Server
                         TrySendPDU(state, response);
                     }
                 }
-                else if (pdu is SCSIDataOutPDU)
+                else if (pdu is SCSIDataOutPDU || pdu is SCSICommandPDU)
                 {
                     // FIXME: the iSCSI target layer MUST deliver the commands for execution (to the SCSI execution engine) in the order specified by CmdSN.
                     // e.g. read requests should not be executed while previous write request data is being received (via R2T)
-                    SCSIDataOutPDU request = (SCSIDataOutPDU)pdu;
-                    ISCSIServer.Log("[{0}][ProcessPDU] SCSIDataOutPDU: Target transfer tag: {1}, LUN: {2}, Buffer offset: {3}, Data segment length: {4}, DataSN: {5}, Final: {6}", state.ConnectionIdentifier, request.TargetTransferTag, (ushort)request.LUN, request.BufferOffset, request.DataSegmentLength, request.DataSN, request.Final);
-                    ISCSIPDU response = TargetResponseHelper.GetSCSIDataOutResponsePDU(request, state.Target, state.SessionParameters, state.ConnectionParameters);
-                    TrySendPDU(state, response);
-                }
-                else if (pdu is SCSICommandPDU)
-                {
-                    SCSICommandPDU command = (SCSICommandPDU)pdu;
-                    ISCSIServer.Log("[{0}][ProcessPDU] SCSICommandPDU: CmdSN: {1}, LUN: {2}, Data segment length: {3}, Expected Data Transfer Length: {4}, Final: {5}", state.ConnectionIdentifier, command.CmdSN, (ushort)command.LUN, command.DataSegmentLength, command.ExpectedDataTransferLength, command.Final);
-                    List<ISCSIPDU> scsiResponseList = TargetResponseHelper.GetSCSIResponsePDU(command, state.Target, state.SessionParameters, state.ConnectionParameters);
-                    foreach (ISCSIPDU response in scsiResponseList)
+                    List<SCSICommandPDU> commandsToExecute;
+                    List<ISCSIPDU> responseList;
+                    if (pdu is SCSIDataOutPDU)
+                    {
+                        SCSIDataOutPDU request = (SCSIDataOutPDU)pdu;
+                        ISCSIServer.Log("[{0}][ProcessPDU] SCSIDataOutPDU: Target transfer tag: {1}, LUN: {2}, Buffer offset: {3}, Data segment length: {4}, DataSN: {5}, Final: {6}", state.ConnectionIdentifier, request.TargetTransferTag, (ushort)request.LUN, request.BufferOffset, request.DataSegmentLength, request.DataSN, request.Final);
+                        responseList = TargetResponseHelper.GetReadyToTransferPDUs(request, state.Target, state.SessionParameters, state.ConnectionParameters, out commandsToExecute);
+                    }
+                    else
+                    {
+                        SCSICommandPDU command = (SCSICommandPDU)pdu;
+                        ISCSIServer.Log("[{0}][ProcessPDU] SCSICommandPDU: CmdSN: {1}, LUN: {2}, Data segment length: {3}, Expected Data Transfer Length: {4}, Final: {5}", state.ConnectionIdentifier, command.CmdSN, (ushort)command.LUN, command.DataSegmentLength, command.ExpectedDataTransferLength, command.Final);
+                        responseList = TargetResponseHelper.GetReadyToTransferPDUs(command, state.Target, state.SessionParameters, state.ConnectionParameters, out commandsToExecute);
+                    }
+
+                    foreach(SCSICommandPDU command in commandsToExecute)
+                    {
+                        List<ISCSIPDU> commandResponseList = TargetResponseHelper.GetSCSICommandResponse(command, state.Target, state.SessionParameters, state.ConnectionParameters);
+                        responseList.AddRange(commandResponseList);
+                    }
+
+                    foreach (ISCSIPDU response in responseList)
                     {
                         TrySendPDU(state, response);
                         if (!clientSocket.Connected)

+ 62 - 55
ISCSI/Server/TargetResponseHelper.cs

@@ -16,10 +16,11 @@ namespace ISCSI.Server
 {
     public class TargetResponseHelper
     {
-        internal static List<ISCSIPDU> GetSCSIResponsePDU(SCSICommandPDU command, ISCSITarget target, SessionParameters session, ConnectionParameters connection)
+        internal static List<ISCSIPDU> GetReadyToTransferPDUs(SCSICommandPDU command, ISCSITarget target, SessionParameters session, ConnectionParameters connection, out List<SCSICommandPDU> commandsToExecute)
         {
             // We return either SCSIResponsePDU or List<SCSIDataInPDU>
             List<ISCSIPDU> responseList = new List<ISCSIPDU>();
+            commandsToExecute = new List<SCSICommandPDU>();
             
             string connectionIdentifier = StateObject.GetConnectionIdentifier(session, connection);
 
@@ -44,6 +45,65 @@ namespace ISCSI.Server
                 return responseList;
             }
 
+            commandsToExecute.Add(command);
+            return responseList;
+        }
+
+        internal static List<ISCSIPDU> GetReadyToTransferPDUs(SCSIDataOutPDU request, ISCSITarget target, SessionParameters session, ConnectionParameters connection, out List<SCSICommandPDU> commandsToExecute)
+        {
+            List<ISCSIPDU> responseList = new List<ISCSIPDU>();
+            commandsToExecute = new List<SCSICommandPDU>();
+
+            string connectionIdentifier = StateObject.GetConnectionIdentifier(session, connection);
+            TransferEntry transfer = connection.GetTransferEntry(request.TargetTransferTag);
+            if (transfer == null)
+            {
+                ISCSIServer.Log("[{0}][GetSCSIDataOutResponsePDU] Invalid TargetTransferTag {1}", connectionIdentifier, request.TargetTransferTag);
+                RejectPDU reject = new RejectPDU();
+                reject.InitiatorTaskTag = request.InitiatorTaskTag;
+                reject.Reason = RejectReason.InvalidPDUField;
+                reject.Data = ByteReader.ReadBytes(request.GetBytes(), 0, 48);
+                responseList.Add(reject);
+                return responseList;
+            }
+
+            ushort LUN = (ushort)request.LUN;
+            Disk disk = target.Disks[LUN];
+            uint offset = request.BufferOffset;
+            uint totalLength = (uint)transfer.Command.ExpectedDataTransferLength;
+
+            // Store segment (we only execute the command after receiving all of its data)
+            Array.Copy(request.Data, 0, transfer.Command.Data, offset, request.DataSegmentLength);
+            
+            ISCSIServer.Log(String.Format("[{0}][GetSCSIDataOutResponsePDU] Buffer offset: {1}, Total length: {2}", connectionIdentifier, offset, totalLength));
+
+            if (offset + request.DataSegmentLength == totalLength)
+            {
+                // Last Data-out PDU
+                commandsToExecute.Add(transfer.Command);
+                return responseList;
+            }
+            else
+            {
+                // Send R2T
+                ReadyToTransferPDU response = new ReadyToTransferPDU();
+                response.InitiatorTaskTag = request.InitiatorTaskTag;
+                response.TargetTransferTag = request.TargetTransferTag;
+                response.R2TSN = transfer.NextR2NSN;
+                response.BufferOffset = offset + request.DataSegmentLength; // where we left off
+                response.DesiredDataTransferLength = Math.Min((uint)connection.TargetMaxRecvDataSegmentLength, totalLength - response.BufferOffset);
+
+                transfer.NextR2NSN++;
+
+                responseList.Add(response);
+                return responseList;
+            }
+        }
+
+        internal static List<ISCSIPDU> GetSCSICommandResponse(SCSICommandPDU command, ISCSITarget target, SessionParameters session, ConnectionParameters connection)
+        {
+            List<ISCSIPDU> responseList = new List<ISCSIPDU>();
+            string connectionIdentifier = StateObject.GetConnectionIdentifier(session, connection);
             ISCSIServer.Log("[{0}] Executing Command: CmdSN: {1}", connectionIdentifier, command.CmdSN);
             byte[] scsiResponse;
             SCSIStatusCodeName status = target.ExecuteCommand(command.CommandDescriptorBlock, command.LUN, command.Data, out scsiResponse);
@@ -80,7 +140,7 @@ namespace ISCSI.Server
                 {
                     int dataSegmentLength = Math.Min(connection.InitiatorMaxRecvDataSegmentLength, bytesLeftToSend);
                     int dataOffset = scsiResponse.Length - bytesLeftToSend;
-                    
+
                     SCSIDataInPDU response = new SCSIDataInPDU();
                     response.InitiatorTaskTag = command.InitiatorTaskTag;
                     if (bytesLeftToSend == dataSegmentLength)
@@ -105,59 +165,6 @@ namespace ISCSI.Server
             return responseList;
         }
 
-        internal static ISCSIPDU GetSCSIDataOutResponsePDU(SCSIDataOutPDU request, ISCSITarget target, SessionParameters session, ConnectionParameters connection)
-        {
-            string connectionIdentifier = StateObject.GetConnectionIdentifier(session, connection);
-            TransferEntry transfer = connection.GetTransferEntry(request.TargetTransferTag);
-            if (transfer == null)
-            {
-                ISCSIServer.Log("[{0}][GetSCSIDataOutResponsePDU] Invalid TargetTransferTag {1}", connectionIdentifier, request.TargetTransferTag);
-                RejectPDU reject = new RejectPDU();
-                reject.InitiatorTaskTag = request.InitiatorTaskTag;
-                reject.Reason = RejectReason.InvalidPDUField;
-                reject.Data = ByteReader.ReadBytes(request.GetBytes(), 0, 48);
-                return reject;
-            }
-
-            ushort LUN = (ushort)request.LUN;
-            Disk disk = target.Disks[LUN];
-            uint offset = request.BufferOffset;
-            uint totalLength = (uint)transfer.Command.ExpectedDataTransferLength;
-
-            // Store segment (we only execute the command after receiving all of its data)
-            Array.Copy(request.Data, 0, transfer.Command.Data, offset, request.DataSegmentLength);
-            
-            ISCSIServer.Log(String.Format("[{0}][GetSCSIDataOutResponsePDU] Buffer offset: {1}, Total length: {2}", connectionIdentifier, offset, totalLength));
-
-            if (offset + request.DataSegmentLength == totalLength)
-            {
-                // Last Data-out PDU
-                ISCSIServer.Log("[{0}] Executing Command: CmdSN: {1}", connectionIdentifier, transfer.Command.CmdSN);
-                byte[] scsiResponse;
-                SCSIStatusCodeName status = target.ExecuteCommand(transfer.Command.CommandDescriptorBlock, transfer.Command.LUN, transfer.Command.Data, out scsiResponse);
-                SCSIResponsePDU response = new SCSIResponsePDU();
-                response.InitiatorTaskTag = request.InitiatorTaskTag;
-                response.Status = status;
-                response.Data = scsiResponse;
-                connection.RemoveTransfer(request.TargetTransferTag);
-                return response;
-            }
-            else
-            {
-                // Send R2T
-                ReadyToTransferPDU response = new ReadyToTransferPDU();
-                response.InitiatorTaskTag = request.InitiatorTaskTag;
-                response.TargetTransferTag = request.TargetTransferTag;
-                response.R2TSN = transfer.NextR2NSN;
-                response.BufferOffset = offset + request.DataSegmentLength; // where we left off
-                response.DesiredDataTransferLength = Math.Min((uint)connection.TargetMaxRecvDataSegmentLength, totalLength - response.BufferOffset);
-
-                transfer.NextR2NSN++;
-
-                return response;
-            }
-        }
-
         public static void EnforceExpectedDataTransferLength(SCSIResponsePDU response, uint expectedDataTransferLength)
         {
             if (response.Data.Length > expectedDataTransferLength)