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.ModeSense6Cdb;
15  import org.jscsi.target.scsi.modeSense.CachingModePage;
16  import org.jscsi.target.scsi.modeSense.HeaderType;
17  import org.jscsi.target.scsi.modeSense.InformationExceptionsControlModePage;
18  import org.jscsi.target.scsi.modeSense.ModePage;
19  import org.jscsi.target.scsi.modeSense.ModePageCode;
20  import org.jscsi.target.scsi.modeSense.ModeParameterList;
21  import org.jscsi.target.scsi.modeSense.ModeParameterListBuilder;
22  import org.jscsi.target.scsi.modeSense.ShortLogicalBlockDescriptor;
23  import org.jscsi.target.settings.SettingsException;
24  import org.slf4j.Logger;
25  import org.slf4j.LoggerFactory;
26  
27  
28  /**
29   * A stage for processing <code>MODE SENSE (6)</code> SCSI commands.
30   * 
31   * @author Andreas Ergenzinger
32   */
33  public final class ModeSenseStage extends TargetFullFeatureStage {
34  
35      private static final Logger LOGGER = LoggerFactory.getLogger(ModeSenseStage.class);
36  
37      public ModeSenseStage (TargetFullFeaturePhase targetFullFeaturePhase) {
38          super(targetFullFeaturePhase);
39      }
40  
41      @Override
42      public void execute (final ProtocolDataUnit pdu) throws IOException , InterruptedException , InternetSCSIException , DigestException , SettingsException {
43  
44          final BasicHeaderSegment bhs = pdu.getBasicHeaderSegment();
45          final SCSICommandParser parser = (SCSICommandParser) bhs.getParser();
46          final ModeSense6Cdb cdb = new ModeSense6Cdb(parser.getCDB());
47  
48          if (LOGGER.isDebugEnabled()) {
49              LOGGER.debug(Boolean.toString(cdb.getDisableBlockDescriptors()));
50              LOGGER.debug(cdb.getPageControl().toString());
51              LOGGER.debug(Integer.toString(cdb.getPageCode()));
52              LOGGER.debug(Integer.toString(cdb.getSubpageCode()));
53              LOGGER.debug("cdb.getAllocationLength() = " + cdb.getAllocationLength());
54              // LOGGER.debug(cdb.getModePage());
55          }
56  
57          // final PageControl pageControl = cdb.getPageControl();//see 8 lines
58          // below
59          final ModePageCode modePageCode = cdb.getModePage();
60  
61          // ModeParameterList and ModeParameterListBuilder common to
62          // all supported ModePage requests
63  
64          ModePage[] modePages = null;
65          if (modePageCode == ModePageCode.INFORMATIONAL_EXCEPTIONS_CONTROL_MODE_PAGE) {
66              // TODO this should to be made dynamic wrt. cdb.getPageControl();
67  
68              modePages = new ModePage[] { getInformationExceptionsControlModePage() };
69  
70          } else if (modePageCode == ModePageCode.CACHING_MODE_PAGE) {
71  
72              modePages = new ModePage[] { getCachingModePage() };
73  
74          } else if (modePageCode == ModePageCode.RETURN_ALL_MODE_PAGES_ONLY) {
75  
76              modePages = new ModePage[] { getInformationExceptionsControlModePage(), getCachingModePage() };
77  
78          }// else modeParameterList stays null
79  
80          // create and send response PDU
81          if (modePages != null) {
82  
83              // create ModeParameterList
84              final ModeParameterListBuilder builder = new ModeParameterListBuilder(HeaderType.MODE_PARAMETER_HEADER_6);
85              builder.setLogicalBlockDescriptors(new ShortLogicalBlockDescriptor(session.getStorageModule().getSizeInBlocks(),// numberOfLogicalBlocks
86              VIRTUAL_BLOCK_SIZE));// logicalBlockLength
87              builder.setModePages(modePages);
88              ModeParameterList modeParameterList = ModeParameterList.build(builder);
89  
90              // send response
91              sendResponse(bhs.getInitiatorTaskTag(),// initiatorTaskTag,
92                      parser.getExpectedDataTransferLength(),// expectedDataTransferLength,
93                      modeParameterList);// responseData
94  
95          } else {
96              /*
97               * The initiator has requested a mode sense page which the jSCSI Target cannot provide. This could be
98               * answered with an Illegal field in CDB message but, there is no good way to identify the exact field at
99               * fault.
100              */
101             throw new InternetSCSIException();
102         }
103 
104     }
105 
106     private static final InformationExceptionsControlModePage getInformationExceptionsControlModePage () {
107         return new InformationExceptionsControlModePage(false,// parametersSaveable
108         false,// performance
109         false,// enableBackgroundFunction
110         false,// enableWarning
111         true,// disableExceptionControl
112         false,// test
113         false,// logErrors
114         0x0,// methodOfReportingInformationalExceptionConditions
115         0,// intervalTimer
116         0);// reportCount
117     }
118 
119     private static final CachingModePage getCachingModePage () {
120         return new CachingModePage(false,// parametersSaveable
121         false,// initiatorControl
122         true,// abortPrefetch
123         false,// cachingAnalysisPermitted
124         false,// discontinuity
125         true,// sizeEnable
126         false,// writebackCacheEnable
127         false,// multiplicationFactor
128         true,// readCacheDisable
129         0x0,// demandReadRetentionPriority
130         0x0,// writeRetentionPriority
131         0,// disablePrefetchTransferLength
132         0,// minimumPrefetch
133         65535,// maximumPrefetch
134         65535,// maximumPrefetchCeiling
135         true,// forceSequentialWrite
136         false,// logicalBlockCacheSegmentSize
137         false,// disableReadAhead
138         false,// nonVolatileCacheDisabled
139         20,// numberOfCacheSegments
140         0);// cacheSegmentSize
141     }
142 
143     public boolean canHandle (final ProtocolDataUnit pdu) {
144         final BasicHeaderSegment bhs = pdu.getBasicHeaderSegment();
145         final SCSICommandParser parser = (SCSICommandParser) bhs.getParser();
146         final ModeSense6Cdb cdb = new ModeSense6Cdb(parser.getCDB());
147         final ModePageCode modePageCode = cdb.getModePage();
148         if (modePageCode == ModePageCode.INFORMATIONAL_EXCEPTIONS_CONTROL_MODE_PAGE) {
149             return true;
150         } else if (modePageCode == ModePageCode.CACHING_MODE_PAGE) {
151             return true;
152         } else if (modePageCode == ModePageCode.RETURN_ALL_MODE_PAGES_ONLY) {
153             return true;
154         } else {
155             return false;
156         }
157     }
158 
159 }