2.1.5.10.20 FSCTL_OFFLOAD_READ
The server provides:
Open: An Open of a DataFile.
InputBuffer: An array of bytes containing a single FSCTL_OFFLOAD_READ_INPUT structure, as specified in [MS-FSCC] section 2.3.41, indicating the Token that indicates the range of the file to offload read, as specified in [MS-FSCC] section 2.1.11.
InputBufferSize: The number of bytes in InputBuffer.
OutputBufferSize: The number of bytes in OutputBuffer.
Upon completion, the object store MUST return:
Status: An NTSTATUS code that specifies the result.
OutputBuffer: An array of bytes that contains a single FSCTL_OFFLOAD_READ_OUTPUT structure, as specified in [MS-FSCC] section 2.3.42, which contains the Token for the read data, as specified in [MS-FSCC] section 2.1.11.
BytesReturned: The number of bytes written to OutputBuffer.
This operation also uses the following local variables:
Boolean (initialized to FALSE): VdlSameAsEof
32-bit unsigned integers (initialized to zero): OutputBufferLength
64-bit unsigned integers (initialized to zero): StartingCluster, ValidDataLength, FileSize, LastClusterInFile, VdlTrimmedCopyLength, and StorageOffloadBytesRead
A list of EXTENTS (initialized to empty): OffloadLCNList
An NTSTATUS code: StorageOffloadReadStatus
A STORAGE_OFFLOAD_TOKEN structure, as specified in [MS-FSCC] section 2.1.11: StorageOffloadReadToken
Support for this read operation is optional. If the object store does not implement this functionality, the operation MUST be failed with STATUS_INVALID_DEVICE_REQUEST.<112>
Pseudocode for the operation is as follows:
If Open.File.Volume.IsOffloadReadSupported is FALSE, the operation MUST be failed with STATUS_NOT_SUPPORTED.
If InputBufferSize is less than the size of the FSCTL_OFFLOAD_READ_INPUT structure size, the operation MUST be failed with STATUS_BUFFER_TOO_SMALL.
If OutputBufferSize is less than the size of the FSCTL_OFFLOAD_READ_OUTPUT structure size, the operation MUST be failed with STATUS_BUFFER_TOO_SMALL.
If InputBuffer.FileOffset is not a multiple of Open.File.Volume. LogicalBytesPerSector, the operation MUST be failed with STATUS_INVALID_PARAMETER.
If InputBuffer.CopyLength is not a multiple of Open.File.Volume.LogicalBytesPerSector, the operation MUST be failed with STATUS_INVALID_PARAMETER.
If InputBuffer.Size is not equal to the size of the FSCTL_OFFLOAD_READ_INPUT structure size, the operation MUST be failed with STATUS_INVALID_PARAMETER.
If the sum of InputBuffer.FileOffset and InputBuffer.CopyLength overflows 64 bits, the operation MUST be failed with STATUS_INVALID_PARAMETER.
If InputBuffer.CopyLength is equal to 0, the operation SHOULD return immediately with STATUS_SUCCESS.
If Open.Stream.StreamType != DataStream, the operation MUST be failed with STATUS_OFFLOAD_READ_FILE_NOT_SUPPORTED.
If Open.Stream.IsSparse is TRUE, the operation MUST be failed with STATUS_OFFLOAD_READ_FILE_NOT_SUPPORTED.
If Open.Stream.IsEncrypted is TRUE, the operation MUST be failed with STATUS_OFFLOAD_READ_FILE_NOT_SUPPORTED.
If Open.Stream.IsCompressed is TRUE, the operation MUST be failed with STATUS_OFFLOAD_READ_FILE_NOT_SUPPORTED.
If Open.Stream.IsDeleted is TRUE, the operation MUST be failed with STATUS_FILE_DELETED.
If InputBuffer.FileOffset / Open.File.Volume.BytesPerCluster is less than 0, the operation MUST be failed with STATUS_INVALID_PARAMETER.
The object store MUST check for byte range lock conflicts using the algorithm described in section 2.1.4.10 with ByteOffset set to InputBuffer.FileOffset, Length set to InputBuffer.CopyLength, IsExclusive set to FALSE, LockIntent set to FALSE, and Open set to Open. If a conflict is detected, the operation MUST be failed with STATUS_FILE_LOCK_CONFLICT.
Set ValidDataLength to Open.Stream.ValidDataLength.
Set FileSize to Open.Stream.Size.
If ValidDataLength is not equal to FileSize, set VdlSameAsEof to FALSE.
Set StartingCluster to InputBuffer.FileOffset / Open.File.Volume.BytesPerCluster.
Set LastClusterInFile to ClustersFromBytesTruncate(Open.File.Volume, FileSize).
If StartingCluster is greater than LastClusterInFile:
The operation MUST be failed with STATUS_END_OF_FILE.
Else If StartingCluster is less than 0:
The operation MUST be failed with STATUS_INVALID_PARAMETER.
EndIf
If InputBuffer.FileOffset is greater than or equal to FileSize, the operation MUST be failed with STATUS_END_OF_FILE.
If InputBuffer.FileOffset is greater than or equal to ValidDataLength:
Set OutputBuffer.Token to the Zero token as defined in [MS-FSCC] section 2.1.11.
The operation MUST return STATUS_SUCCESS, with BytesReturned set to OutputBufferLength, and OutputBuffer.Flags set to OFFLOAD_READ_FLAG_ALL_ZERO_BEYOND_CURRENT_RANGE.
EndIf
If the sum of InputBuffer.FileOffset and InputBuffer.CopyLength is greater than ValidDataLength:
Set InputBuffer.CopyLength to ValidDataLength – InputBuffer.FileOffset.
If VdlSameAsEof is TRUE:
Set InputBuffer.CopyLength to BlockAlign(InputBuffer.CopyLength, Open.File.Volume.LogicalBytesPerSector).
Set VdlTrimmedCopyLength to InputBuffer.CopyLength.
Set OutputBuffer.Flags to OFFLOAD_READ_FLAG_ALL_ZERO_BEYOND_CURRENT_RANGE.
EndIf
EndIf
For Each Extent in Open.Stream.ExtentList spanned by the range defined by Input.FileOffset and Input.CopyLength:
Append the partial or full Extent to OffloadLCNList.
EndFor
Construct the offload read command with the OffloadLCNList as the ranges, and Token length specified in InputBuffer.CopyLength as described in [INCITS-T10/11-059] and send it to the underlying storage subsystem, storing the status from the operation in StorageOffloadReadStatus, the number of bytes represented by the token in StorageOffloadBytesRead, and the Token in StorageOffloadToken.
If the call was successful:
Set OutputBuffer.Token to StorageOffloadToken.
Set OutputBuffer.TransferLength to StorageOffloadBytesRead.
If OutputBuffer.Flag has the bit OFFLOAD_READ_FLAG_ALL_ZERO_BEYOND_CURRENT_RANGE set:
If OutputBuffer.TransferLength is less than VdlTrimmedCopyLength, clear the OFFLOAD_READ_FLAG_ALL_ZERO_BEYOND_CURRENT_RANGE bit in OutputBuffer.Flags.
EndIf
Else:
If StorageOffloadReadStatus is equal to STATUS_NOT_SUPPORTED or if StorageOffloadReadStatus is equal to STATUS_DEVICE_FEATURE_NOT_SUPPORTED, then set Open.File.Volume.IsOffloadReadSupported to FALSE.
EndIf
Upon successful completion of the operation, the object store MUST return:
BytesReturned set to OutputBufferLength.
Status set to STATUS_SUCCESS.