| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
| FormatUnitStage |
|
| 1.5;1.5 |
| 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 | 0 | private static final Logger LOGGER = LoggerFactory.getLogger(ReadStage.class); |
| 52 | ||
| 53 | public FormatUnitStage (TargetFullFeaturePhase targetFullFeaturePhase) { | |
| 54 | 0 | super(targetFullFeaturePhase); |
| 55 | 0 | } |
| 56 | ||
| 57 | @Override | |
| 58 | public void execute (ProtocolDataUnit pdu) throws IOException , InterruptedException , InternetSCSIException , DigestException , SettingsException { | |
| 59 | ||
| 60 | 0 | LOGGER.debug("Initiator has sent FORMAT UNIT command."); |
| 61 | ||
| 62 | 0 | final BasicHeaderSegment bhs = pdu.getBasicHeaderSegment(); |
| 63 | 0 | final SCSICommandParser parser = (SCSICommandParser) bhs.getParser(); |
| 64 | ||
| 65 | 0 | ProtocolDataUnit responsePdu = null;// the response PDU |
| 66 | ||
| 67 | // get command details in CDB | |
| 68 | 0 | final FormatUnitCDB cdb = new FormatUnitCDB(parser.getCDB()); |
| 69 | 0 | final FieldPointerSenseKeySpecificData[] illegalFieldPointers = cdb.getIllegalFieldPointers(); |
| 70 | ||
| 71 | 0 | if (illegalFieldPointers != null) { |
| 72 | // an illegal request has been made | |
| 73 | ||
| 74 | 0 | 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 | 0 | 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 | 0 | } 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 | 0 | responsePdu = createScsiResponsePdu(SCSIStatus.GOOD,// status |
| 119 | bhs.getInitiatorTaskTag(),// initiatorTaskTag, | |
| 120 | parser.getExpectedDataTransferLength(),// expectedDataTransferLength, | |
| 121 | 0);// responseDataSize | |
| 122 | } | |
| 123 | ||
| 124 | // send response | |
| 125 | 0 | connection.sendPdu(responsePdu); |
| 126 | 0 | } |
| 127 | ||
| 128 | } |