package org.jscsi.target.connection.stage.fullfeature; import java.io.IOException; import java.security.DigestException; import org.jscsi.exception.InternetSCSIException; import org.jscsi.parser.BasicHeaderSegment; import org.jscsi.parser.ProtocolDataUnit; import org.jscsi.parser.scsi.SCSICommandParser; import org.jscsi.parser.scsi.SCSIResponseParser; import org.jscsi.parser.scsi.SCSIStatus; import org.jscsi.target.connection.TargetPduFactory; import org.jscsi.target.connection.phase.TargetFullFeaturePhase; import org.jscsi.target.scsi.ScsiResponseDataSegment; import org.jscsi.target.scsi.cdb.FormatUnitCDB; import org.jscsi.target.scsi.sense.AdditionalSenseBytes; import org.jscsi.target.scsi.sense.AdditionalSenseCodeAndQualifier; import org.jscsi.target.scsi.sense.ErrorType; import org.jscsi.target.scsi.sense.FixedFormatSenseData; import org.jscsi.target.scsi.sense.SenseKey; import org.jscsi.target.scsi.sense.information.FourByteInformation; import org.jscsi.target.scsi.sense.senseDataDescriptor.senseKeySpecific.FieldPointerSenseKeySpecificData; import org.jscsi.target.settings.SettingsException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A stage for processing <code>FORMAT UNIT</code> SCSI commands. * <p> * The <code>FORMAT UNIT</code> command requests that the device server format the medium into application * client accessible logical blocks as specified in the number of logical blocks and logical block length * values received in the last mode parameter block descriptor in a <code>MODE SELECT</code> command (see * SPC-4). In addition, the device server may certify the medium and create control structures for the * management of the medium and defects. * <p> * The degree that the medium is altered by this command is vendor specific. * <p> * If a device server receives a <code>FORMAT UNIT</code> command before receiving a MODE SELECT command with * a mode parameter block descriptor, then the device server shall use the number of logical blocks and * logical block length at which the logical unit is currently formatted (i.e., no change is made to the * number of logical blocks and the logical block length of the logical unit during the format operation). * <p> * <code>FORMAT UNIT</code> commands received by the jSCI Target will not lead to any persistent changes of * the virtual logical unit. * * @author Andreas Ergenzinger */ public class FormatUnitStage extends TargetFullFeatureStage { private static final Logger LOGGER = LoggerFactory.getLogger(ReadStage.class); public FormatUnitStage(TargetFullFeaturePhase targetFullFeaturePhase) { super(targetFullFeaturePhase); } @Override public void execute(ProtocolDataUnit pdu) throws IOException, InterruptedException, InternetSCSIException, DigestException, SettingsException { LOGGER.debug("Initiator has sent FORMAT UNIT command."); final BasicHeaderSegment bhs = pdu.getBasicHeaderSegment(); final SCSICommandParser parser = (SCSICommandParser)bhs.getParser(); ProtocolDataUnit responsePdu = null;// the response PDU // get command details in CDB final FormatUnitCDB cdb = new FormatUnitCDB(parser.getCDB()); final FieldPointerSenseKeySpecificData[] illegalFieldPointers = cdb.getIllegalFieldPointers(); if (illegalFieldPointers != null) { // an illegal request has been made FixedFormatSenseData senseData = new FixedFormatSenseData(false,// valid ErrorType.CURRENT,// error type false,// file mark false,// end of medium false,// incorrect length indicator SenseKey.ILLEGAL_REQUEST,// sense key new FourByteInformation(),// information new FourByteInformation(),// command specific information AdditionalSenseCodeAndQualifier.INVALID_FIELD_IN_CDB,// additional // sense // code // and // qualifier (byte)0,// field replaceable unit code illegalFieldPointers[0],// sense key specific data, only // report first problem new AdditionalSenseBytes());// additional sense bytes responsePdu = TargetPduFactory.createSCSIResponsePdu(false,// bidirectionalReadResidualOverflow false,// bidirectionalReadResidualUnderflow false,// residualOverflow false,// residualUnderflow, SCSIResponseParser.ServiceResponse.COMMAND_COMPLETED_AT_TARGET,// response, SCSIStatus.CHECK_CONDITION,// status, bhs.getInitiatorTaskTag(),// initiatorTaskTag, 0,// snackTag 0,// expectedDataSequenceNumber 0,// bidirectionalReadResidualCount 0,// residualCount new ScsiResponseDataSegment(senseData, parser.getExpectedDataTransferLength()));// data // segment } else { // PDU is okay // carry out command /* * If we were nice, we would have to get (we would actually have to * save it first) the number of blocks and the block length * requested by the initiator in the last MODE SENSE command and * then change the logical block layout accordingly. * * However, since the target is not required by the SCSI standard to * make those changes ("The degree that the medium is altered by * this command is vendor specific."), doing nothing is okay. */ responsePdu = createScsiResponsePdu(SCSIStatus.GOOD,// status bhs.getInitiatorTaskTag(),// initiatorTaskTag, parser.getExpectedDataTransferLength(),// expectedDataTransferLength, 0);// responseDataSize } // send response connection.sendPdu(responsePdu); } }