2.1.5.9.17 FSCTL_OFFLOAD_WRITE
The server provides:
-
Open: An Open of a DataFile.
-
InputBuffer: An array of bytes containing a single FSCTL_OFFLOAD_WRITE_INPUT structure, as specified in [MS-FSCC] section 2.3.76, indicating the Token to use as the source, and the range of the file to be offload written to, as specified in [MS-FSCC] section 2.3.75.
-
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_WRITE_OUTPUT structure, as specified in [MS-FSCC] section 2.3.77.
-
BytesReturned: The number of bytes written to OutputBuffer.
This operation also uses the following local variables:
-
32-bit unsigned integers (initialized to zero): OutputBufferLength
-
64-bit unsigned integers (initialized to zero): NewValidDataLength, ValidDataLength, FileSize, and StorageOffloadBytesWritten.
-
A list of EXTENTS (initialized to empty): OffloadLCNList
-
An NTSTATUS code: StorageOffloadWriteStatus
Support for this write operation is optional. If the object store does not implement this functionality, the operation MUST be failed with STATUS_INVALID_DEVICE_REQUEST.<67>
Pseudocode for the operation is as follows:
-
If Open.Volume.IsReadOnly is TRUE, the operation MUST be failed with STATUS_MEDIA_WRITE_PROTECTED.
-
If Open.Volume.IsOffloadWriteSupported is FALSE, the operation MUST be failed with STATUS_NOT_SUPPORTED.
-
If InputBufferSize is less than the size of the FSCTL_OFFLOAD_WRITE_INPUT structure size, the operation MUST be failed with STATUS_BUFFER_TOO_SMALL.
-
If OutputBufferSize is less than the size of the FSCTL_OFFLOAD_WRITE_OUTPUT structure size, the operation MUST be failed with STATUS_BUFFER_TOO_SMALL.
-
If InputBuffer.FileOffset is NOT a multiple of Open.Volume.BytesPerLogicalSector, the operation MUST be failed with STATUS_INVALID_PARAMETER.
-
If InputBuffer.CopyLength is NOT a multiple of Open.Volume.BytesPerLogicalSector, the operation MUST be failed with STATUS_INVALID_PARAMETER.
-
If InputBuffer.TransferOffset is NOT a multiple of Open.Volume.BytesPerLogicalSector, the operation MUST be failed with STATUS_INVALID_PARAMETER.
-
If InputBuffer.Size is not equal to the size of the FSCTL_OFFLOAD_WRITE_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_WRITE_FILE_NOT_SUPPORTED.
-
If Open.Stream.IsSparse is TRUE, the operation MUST be failed with STATUS_OFFLOAD_WRITE_FILE_NOT_SUPPORTED.
-
If Open.Stream.IsEncrypted is TRUE, the operation MUST be failed with STATUS_OFFLOAD_WRITE_FILE_NOT_SUPPORTED.
-
If Open.Stream.IsCompressed is TRUE, the operation MUST be failed with STATUS_OFFLOAD_WRITE_FILE_NOT_SUPPORTED.
-
If Open.Stream.IsDeleted is TRUE, the operation MUST be failed with STATUS_FILE_DELETED.
-
If InputBuffer.FileOffset / Open.Volume.BytesPerCluster is less than 0, the operation MUST be failed with STATUS_INVALID_PARAMETER.
-
If (InputBuffer.FileOffset + InputBuffer.CopyLength) is greater than Open.Volume.MaxFileSize, the operation MUST be failed with STATUS_INVALID_PARAMETER.
-
If Open.Volume.IsUsnJournalActive is TRUE, the object store MUST post a USN change as per section 2.1.4.11 with File equal to File, Reason equal to USN_REASON_DATA_OVERWRITE, and FileName equal to Open.File.Name.
-
Set FileSize to Open.Stream.Size.
-
Set ValidDataLength to Open.Stream.ValidDataLength.
-
If InputBuffer.FileOffset is greater than or equal to Open.Stream.FileSize, the operation MUST be failed with STATUS_END_OF_FILE.
-
If InputBuffer.FileOffset is greater than ValidDataLength, the operation MUST be failed with STATUS_BEYOND_VDL.
-
For Each Extent in Open.Stream.ExtentList spanned by the range defined by InputBuffer.FileOffset and InputBuffer.CopyLength:
-
Append the partial or full Extent to OffloadLCNList.
-
-
EndFor
-
Construct the offload write command with the OffloadLCNList as the ranges, Token from InputBuffer.Token, token offset from InputBuffer.TransferOffset, and write length from InputBuffer.CopyLength as defined in [INCITS-T10/11-059] and send it to the underlying storage subsystem. Store the status from the operation in StorageOffloadWriteStatus, and the number of bytes written in StorageOffloadBytesWritten.
-
If the operation was successful:
-
Set NewValidDataLength to InputBuffer.FileOffset + StorageOffloadBytesWritten.
-
If NewValidDataLength is greater than ValidDataLength:
-
Set Open.Stream.VDL to NewValidDataLength.
-
-
EndIf
-
Set OutputBuffer.LengthWritten to StorageOffloadBytesWritten.
-
Set OutputBuffer.Size to the size of the FSCTL_OFFLOAD_WRITE_OUTPUT structure.
-
Set OutputBuffer.Flags to 0.
-
-
Else:
-
If StorageOffloadWriteStatus is equal to STATUS_NOT_SUPPORTED or if OffloadWriteStatus is equal to STATUS_DEVICE_FEATURE_NOT_SUPPORTED, then set Open.Volume.IsOffloadWriteSupported to FALSE.
-
-
EndIf
-
Upon successful completion of the operation, the object store MUST return:
-
BytesReturned set to OutputBufferLength.
-
Status set to STATUS_SUCCESS.
-