View Javadoc

1   package org.jscsi.target.connection.stage.fullfeature;
2   
3   
4   import java.io.IOException;
5   import java.security.DigestException;
6   
7   import org.jscsi.exception.InternetSCSIException;
8   import org.jscsi.parser.BasicHeaderSegment;
9   import org.jscsi.parser.ProtocolDataUnit;
10  import org.jscsi.parser.scsi.SCSICommandParser;
11  import org.jscsi.parser.scsi.SCSIResponseParser;
12  import org.jscsi.parser.scsi.SCSIStatus;
13  import org.jscsi.target.connection.TargetPduFactory;
14  import org.jscsi.target.connection.phase.TargetFullFeaturePhase;
15  import org.jscsi.target.scsi.ScsiResponseDataSegment;
16  import org.jscsi.target.scsi.cdb.FormatUnitCDB;
17  import org.jscsi.target.scsi.sense.AdditionalSenseBytes;
18  import org.jscsi.target.scsi.sense.AdditionalSenseCodeAndQualifier;
19  import org.jscsi.target.scsi.sense.ErrorType;
20  import org.jscsi.target.scsi.sense.FixedFormatSenseData;
21  import org.jscsi.target.scsi.sense.SenseKey;
22  import org.jscsi.target.scsi.sense.information.FourByteInformation;
23  import org.jscsi.target.scsi.sense.senseDataDescriptor.senseKeySpecific.FieldPointerSenseKeySpecificData;
24  import org.jscsi.target.settings.SettingsException;
25  import org.slf4j.Logger;
26  import org.slf4j.LoggerFactory;
27  
28  
29  /**
30   * A stage for processing <code>FORMAT UNIT</code> SCSI commands.
31   * <p>
32   * The <code>FORMAT UNIT</code> command requests that the device server format the medium into application client
33   * accessible logical blocks as specified in the number of logical blocks and logical block length values received in
34   * the last mode parameter block descriptor in a <code>MODE SELECT</code> command (see SPC-4). In addition, the device
35   * server may certify the medium and create control structures for the management of the medium and defects.
36   * <p>
37   * The degree that the medium is altered by this command is vendor specific.
38   * <p>
39   * If a device server receives a <code>FORMAT UNIT</code> command before receiving a MODE SELECT command with a mode
40   * parameter block descriptor, then the device server shall use the number of logical blocks and logical block length at
41   * which the logical unit is currently formatted (i.e., no change is made to the number of logical blocks and the
42   * logical block length of the logical unit during the format operation).
43   * <p>
44   * <code>FORMAT UNIT</code> commands received by the jSCI Target will not lead to any persistent changes of the virtual
45   * logical unit.
46   * 
47   * @author Andreas Ergenzinger
48   */
49  public class FormatUnitStage extends TargetFullFeatureStage {
50  
51      private static final Logger LOGGER = LoggerFactory.getLogger(ReadStage.class);
52  
53      public FormatUnitStage (TargetFullFeaturePhase targetFullFeaturePhase) {
54          super(targetFullFeaturePhase);
55      }
56  
57      @Override
58      public void execute (ProtocolDataUnit pdu) throws IOException , InterruptedException , InternetSCSIException , DigestException , SettingsException {
59  
60          LOGGER.debug("Initiator has sent FORMAT UNIT command.");
61  
62          final BasicHeaderSegment bhs = pdu.getBasicHeaderSegment();
63          final SCSICommandParser parser = (SCSICommandParser) bhs.getParser();
64  
65          ProtocolDataUnit responsePdu = null;// the response PDU
66  
67          // get command details in CDB
68          final FormatUnitCDB cdb = new FormatUnitCDB(parser.getCDB());
69          final FieldPointerSenseKeySpecificData[] illegalFieldPointers = cdb.getIllegalFieldPointers();
70  
71          if (illegalFieldPointers != null) {
72              // an illegal request has been made
73  
74              FixedFormatSenseData senseData = new FixedFormatSenseData(false,// valid
75              ErrorType.CURRENT,// error type
76              false,// file mark
77              false,// end of medium
78              false,// incorrect length indicator
79              SenseKey.ILLEGAL_REQUEST,// sense key
80              new FourByteInformation(),// information
81              new FourByteInformation(),// command specific information
82              AdditionalSenseCodeAndQualifier.INVALID_FIELD_IN_CDB,// additional
83                                                                   // sense
84                                                                   // code
85                                                                   // and
86                                                                   // qualifier
87              (byte) 0,// field replaceable unit code
88              illegalFieldPointers[0],// sense key specific data, only
89                                      // report first problem
90              new AdditionalSenseBytes());// additional sense bytes
91  
92              responsePdu = TargetPduFactory.createSCSIResponsePdu(false,// bidirectionalReadResidualOverflow
93                      false,// bidirectionalReadResidualUnderflow
94                      false,// residualOverflow
95                      false,// residualUnderflow,
96                      SCSIResponseParser.ServiceResponse.COMMAND_COMPLETED_AT_TARGET,// response,
97                      SCSIStatus.CHECK_CONDITION,// status,
98                      bhs.getInitiatorTaskTag(),// initiatorTaskTag,
99                      0,// snackTag
100                     0,// expectedDataSequenceNumber
101                     0,// bidirectionalReadResidualCount
102                     0,// residualCount
103                     new ScsiResponseDataSegment(senseData, parser.getExpectedDataTransferLength()));// data
104                                                                                                     // segment
105 
106         } else {
107             // PDU is okay
108 
109             // carry out command
110             /*
111              * If we were nice, we would have to get (we would actually have to save it first) the number of blocks and
112              * the block length requested by the initiator in the last MODE SENSE command and then change the logical
113              * block layout accordingly. However, since the target is not required by the SCSI standard to make those
114              * changes ("The degree that the medium is altered by this command is vendor specific."), doing nothing is
115              * okay.
116              */
117 
118             responsePdu = createScsiResponsePdu(SCSIStatus.GOOD,// status
119                     bhs.getInitiatorTaskTag(),// initiatorTaskTag,
120                     parser.getExpectedDataTransferLength(),// expectedDataTransferLength,
121                     0);// responseDataSize
122         }
123 
124         // send response
125         connection.sendPdu(responsePdu);
126     }
127 
128 }