2.1.5.10.6 FSCTL_FILE_LEVEL_TRIM

msdn link

The server provides:

  • Open: An Open of a DataFile.

  • InputBuffer: An array of bytes containing a single FILE_LEVEL_TRIM structure, followed by zero or more FILE_LEVEL_TRIM_RANGE structures, as specified in [MS-FSCC] section 2.3.13.1.

  • InputBufferSize: The number of bytes in InputBuffer.

  • OutputBufferSize: The maximum number of bytes to return in OutputBuffer.

On completion, the object store MUST return:

  • Status: An NTSTATUS code that specifies the result.

  • OutputBuffer: An optional array of bytes that contains a single FILE_LEVEL_TRIM_OUTPUT structure, as specified in ([MS-FSCC] section 2.3.14).

  • BytesReturned: The number of bytes written to OutputBuffer.

This operation also uses the following local variables:

  • 64-bit unsigned integers (initialized to zero): AlignmentAdjust, TempOffLen, TrimRange, TrimOffset.

  • An NTSTATUS code: TrimStatus.

Support for this operation is optional. If the object store does not implement this functionality, the operation MUST be failed with STATUS_INVALID_DEVICE_REQUEST.<87>

Pseudocode for the operation is as follows:

  • If Open.Stream.IsEncrypted is TRUE OR Open.Stream.IsCompressed is TRUE, the operation MUST be failed with STATUS_INVALID_PARAMETER.

  • If InputBuffer.Size is < sizeof(FILE_LEVEL_TRIM), the operation MUST be failed with STATUS_INVALID_PARAMETER.

  • If InputBuffer.NumRanges is <= 0, the operation MUST be failed with STATUS_INVALID_PARAMETER.

  • If InputBuffer.NumRanges * sizeof(FILE_LEVEL_TRIM_RANGE) overflows 32-bits, the operation MUST be failed with STATUS_INVALID_PARAMETER.

  • If InputBuffer.NumRanges * sizeof(FILE_LEVEL_TRIM_RANGE) + sizeof(FILE_LEVEL_TRIM) overflows 32-bits, the operation MUST be failed with STATUS_INVALID_PARAMETER.

  • If OutputBufferSize != 0 AND OutputBufferSize is < sizeof(FILE_LEVEL_TRIM_OUTPUT), the operation MUST be failed with STATUS_INVALID_PARAMETER.

  • 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 Open.File, Reason equal to USN_REASON_DATA_OVERWRITE, and FileName equal to Open.File.Name.

  • Set OutputBuffer.NumRangesProcessed = 0.

  • For each TrimRange in InputBuffer.Ranges:

    • Set TrimOffset = TrimRange.Offset

    • Set TrimLength = TrimRange.Length

    • If ((TrimOffset % Open.File.Volume.SystemPageSize) != 0):

      • AlignmentAdjust = TrimOffset % Open.File.Volume.SystemPageSize

      • If (TrimOffset + Open.File.Volume.SystemPageSizeAlignmentAdjust) overflows 64-bits, the operation fails with STATUS_INTEGER_OVERFLOW.

      • If (TrimLength >= (Open.File.Volume.SystemPageSizeAlignmentAdjust):

        • Decrement TrimLength by (Open.File.Volume.SystemPageSizeAlignmentAdjust)

      • Else:

        • Set TrimLength to 0

      • EndIf

      • If (TrimOffset < Open.Stream.AllocationSize):

        • Set TempOffLen to TrimOffset + TrimLength

        • If TempOffLen overflows 64-bits, the operation MUST be failed with STATUS_INTEGER_OVERFLOW.

        • If TempOffLen > Open.Stream.AllocationSize:

          • TrimLength = Open.Stream.AllocationSizeTrimOffset

        • EndIf

      • EndIf

      • Decrement TrimLength by (TrimLength % Open.File.Volume.SystemPageSize)

      • If TrimLength == 0, skip further processing on this range and continue to the next range.

      • The object store MUST check for byte range lock conflicts using the algorithm described in section 2.1.4.10 with ByteOffset set to TrimOffset, Length set to TrimLength, 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.

        Construct a list of the LBAs that the object store denotes as the range of the file specified with TrimOffset and TrimLength. Send a TRIM command to the underlying storage device with the constructed list of LBAs. For ATA devices, this command is the T13 defined "TRIM". For SCSI/SAS devices, this command is the T10 defined "UNMAP". Store the status from the operation in TrimStatus.

      • If the command was successful:

        • Increment OutputBuffer.NumRanges by 1

      • Else,

        • The operation MUST return immediately with status set to TrimStatus.

      • EndIf

    • EndFor

    • Upon successful completion of the operation, the object store MUST return:

      • BytesReturned set to 0 If OutputBufferSize == 0, sizeof(FILE_LEVEL_TRIM_OUTPUT) otherwise

      • Status set to STATUS_SUCCESS.