View Javadoc

1   package org.jscsi.target.connection.stage.fullfeature;
2   
3   
4   import static org.jscsi.target.storage.IStorageModule.VIRTUAL_BLOCK_SIZE;
5   
6   import java.io.IOException;
7   import java.security.DigestException;
8   
9   import org.jscsi.exception.InternetSCSIException;
10  import org.jscsi.parser.BasicHeaderSegment;
11  import org.jscsi.parser.ProtocolDataUnit;
12  import org.jscsi.parser.scsi.SCSICommandParser;
13  import org.jscsi.target.connection.phase.TargetFullFeaturePhase;
14  import org.jscsi.target.scsi.cdb.ReadCapacity10Cdb;
15  import org.jscsi.target.scsi.cdb.ReadCapacity16Cdb;
16  import org.jscsi.target.scsi.cdb.ReadCapacityCdb;
17  import org.jscsi.target.scsi.cdb.ScsiOperationCode;
18  import org.jscsi.target.scsi.readCapacity.ReadCapacity10ParameterData;
19  import org.jscsi.target.scsi.readCapacity.ReadCapacity16ParameterData;
20  import org.jscsi.target.scsi.readCapacity.ReadCapacityParameterData;
21  import org.jscsi.target.scsi.sense.AdditionalSenseCodeAndQualifier;
22  import org.jscsi.target.scsi.sense.senseDataDescriptor.senseKeySpecific.FieldPointerSenseKeySpecificData;
23  import org.jscsi.target.settings.SettingsException;
24  import org.slf4j.Logger;
25  import org.slf4j.LoggerFactory;
26  
27  
28  public final class ReadCapacityStage extends TargetFullFeatureStage {
29  
30      private static final Logger LOGGER = LoggerFactory.getLogger(ReadCapacityStage.class);
31  
32      public ReadCapacityStage (final TargetFullFeaturePhase targetFullFeaturePhase) {
33          super(targetFullFeaturePhase);
34      }
35  
36      @Override
37      public void execute (ProtocolDataUnit pdu) throws IOException , InterruptedException , InternetSCSIException , DigestException , SettingsException {
38  
39          // find out the type of READ CAPACITY command ((10) or (16))
40          final BasicHeaderSegment bhs = pdu.getBasicHeaderSegment();
41          final SCSICommandParser parser = (SCSICommandParser) bhs.getParser();
42          final ScsiOperationCode opCode = ScsiOperationCode.valueOf(parser.getCDB().get(0));
43          ReadCapacityCdb cdb;
44          if (opCode == ScsiOperationCode.READ_CAPACITY_10)
45              cdb = new ReadCapacity10Cdb(parser.getCDB());
46          else if (opCode == ScsiOperationCode.READ_CAPACITY_16)
47              cdb = new ReadCapacity16Cdb(parser.getCDB());
48          else {
49              // programmer error, we should not be here, close the connection
50              throw new InternetSCSIException("wrong SCSI Operation Code " + opCode + " in ReadCapacityStage");
51          }
52  
53          /*
54           * Everything is fine, carry on. The PMI bit of the command descriptor block is ignored, since there is no way
55           * to know if "substantial vendor specific delay in data transfer may be encountered" after the address in the
56           * LOGICAL BLOCK ADDRESS field. Therefore we always try to return the whole length of the storage medium.
57           */
58  
59          // make sure that the LOGICAL BLOCK ADDRESS field is valid and send
60          // appropriate response
61          if (session.getStorageModule().checkBounds(cdb.getLogicalBlockAddress(), 0) != 0) {
62              // invalid, log error, send error PDU, and return
63              LOGGER.error("encountered " + cdb.getClass() + " in ReadCapacityStage with " + "LOGICAL BLOCK ADDRESS = " + cdb.getLogicalBlockAddress());
64  
65              final FieldPointerSenseKeySpecificData fp = new FieldPointerSenseKeySpecificData(true,// senseKeySpecificDataValid
66              true,// commandData (i.e. invalid field in CDB)
67              false,// bitPointerValid
68              0,// bitPointer, reserved since invalid
69              0);// fieldPointer to the SCSI OpCode field
70              final FieldPointerSenseKeySpecificData[] fpArray = new FieldPointerSenseKeySpecificData[] { fp };
71              final ProtocolDataUnit responsePdu = createFixedFormatErrorPdu(fpArray,// senseKeySpecificData
72                      AdditionalSenseCodeAndQualifier.LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE,// additionalSenseCodeAndQualifier
73                      bhs.getInitiatorTaskTag(),// initiatorTaskTag
74                      parser.getExpectedDataTransferLength());// expectedDataTransferLength
75              connection.sendPdu(responsePdu);
76              return;
77          } else {
78              // send PDU with requested READ CAPACITY parameter data
79              ReadCapacityParameterData parameterData;
80              if (cdb instanceof ReadCapacity10Cdb)
81                  parameterData = new ReadCapacity10ParameterData(session.getStorageModule().getSizeInBlocks(),// returnedLogicalBlockAddress
82                  VIRTUAL_BLOCK_SIZE);// logicalBlockLengthInBytes
83              else
84                  parameterData = new ReadCapacity16ParameterData(session.getStorageModule().getSizeInBlocks(),// returnedLogicalBlockAddress
85                  VIRTUAL_BLOCK_SIZE);// logicalBlockLengthInBytes
86  
87              sendResponse(bhs.getInitiatorTaskTag(),// initiatorTaskTag,
88                      parser.getExpectedDataTransferLength(),// expectedDataTransferLength,
89                      parameterData);// responseData
90          }
91      }
92  
93  }