2.1.5.10.21 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.43, 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.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_WRITE_OUTPUT structure, as specified in [MS-FSCC] section 2.3.44.

  • 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.<113>

Pseudocode for the operation is as follows:

  • If Open.File.Volume.IsReadOnly is TRUE, the operation MUST be failed with STATUS_MEDIA_WRITE_PROTECTED.

  • If Open.File.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.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.TransferOffset 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_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.File.Volume.BytesPerCluster is less than 0, the operation MUST be failed with STATUS_INVALID_PARAMETER.

  • If (InputBuffer.FileOffset + InputBuffer.CopyLength) is greater than Open.File.Volume.MaxFileSize, 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 TRUE, LockIntent set to FALSE, and Open set to Open. If a conflict is detected, the operation MUST be failed with STATUS_FILE_LOCK_CONFLICT.

  • If Open.File.Volume.IsUsnJournalActive is TRUE, the object store MUST post a USN change as specified in 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 StorageOffloadWriteStatus is equal to STATUS_DEVICE_FEATURE_NOT_SUPPORTED, then set Open.File.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.