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 }