// winioctl.h
// CTL_CODE(0x0009, 0x082, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define FSCTL_FILE_LEVEL_TRIM 0x00098208
View the official Win32 API reference// ntifs.h
// CTL_CODE(0x0009, 0x082, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define FSCTL_FILE_LEVEL_TRIM 0x00098208
View the official Windows hardware development documentationNo description available.
Indicates ranges within the specified file that do not need to be stored by the storage system.
To perform this operation, call the DeviceIoControl function with the following parameters.
BOOL DeviceIoControl(
(HANDLE) hDevice, // Handle to a file
FSCTL_FILE_LEVEL_TRIM, // dwIoControlCode
(LPVOID) lpInBuffer, // Input buffer
(DWORD) nInBufferSize, // Size of input buffer
(LPVOID) lpOutBuffer, // Output buffer
(DWORD) nOutBufferSize, // Size of output buffer
(LPDWORD) lpBytesReturned, // Number of bytes returned
(LPOVERLAPPED) lpOverlapped // OVERLAPPED structure
);
Irp->IoStatus.Status is set to STATUS_SUCCESS if the request is successful.
Otherwise, Status to the appropriate error condition as a NTSTATUS code.
For more information, see NTSTATUS Values.
The FSCTL_FILE_LEVEL_TRIM control code is a hint to the underlying storage system. When a range of bytes has been trimmed, if that range is later read again, the data returned may be the original data before the trim operation—all zeros (0x00 bytes), all ones (0xff bytes), or a combination of these. Before the trim operation is passed to the underlying storage system, the input ranges are reduced to align with page boundaries (4,096 bytes on 32-bit and x64-based editions of Windows, 8,192 bytes on Itanium-Based editions of Windows).
If an error occurs while processing the FILE_LEVEL_TRIM_RANGE entries that follow the FILE_LEVEL_TRIM structure in the input buffer pointed to by the lpInBuffer parameter, processing stops and the NumRangesProcessed member of the FILE_LEVEL_TRIM_OUTPUT structure pointed to by the lpOutBuffer parameter will indicate the ranges that were successfully processed. Any ranges between NumRangesProcessed and the NumRanges member of the FILE_LEVEL_TRIM structure were not processed.
The FSCTL_FILE_LEVEL_TRIM control code is not compatible with encrypted or compressed files (GetFileAttributes returns FILE_ATTRIBUTE_ENCRYPTED or FILE_ATTRIBUTE_COMPRESSED) and will fail with ERROR_INVALID_PARAMETER. Sparse files (indicated by FILE_ATTRIBUTE_SPARSE_FILE) are supported, but only ranges that have been allocated can be trimmed. Files on volumes encrypted by BitLocker technology are supported, while individually encrypted files are not.
The FSCTL_FILE_LEVEL_TRIM control code does not participate in transactions. If a FSCTL_FILE_LEVEL_TRIM control code is processed during a transaction, and the transaction is aborted, the trim will not be rolled back with the transaction.
Ranges that are successfully trimmed will be removed from the filesystem cache.
Ranges that are trimmed can be beyond the valid data length (VDL) up to the end-of-file (EOF).
In Windows 8 and Windows Server 2012, this code is supported by the following technologies.
| Technology | Supported |
|---|---|
| Server Message Block (SMB) 3.0 protocol | Yes |
| SMB 3.0 Transparent Failover (TFO) | Yes |
| SMB 3.0 with Scale-out File Shares (SO) | Yes |
| Cluster Shared Volume File System (CsvFS) | Yes |
| Resilient File System (ReFS) | No |
The FSCTL_FILE_LEVEL_TRIM control code provides a method to trim data ranges with in a file. The file trim ranges are translated to the underlying storage device allowing it to optimize its resource organization to improve access performance. An FSCTL_FILE_LEVEL_TRIM request allows a virtual disk file to remain allocated at a fixed size while trimming physical storage to correspond to data ranges freed on the virtual disk.
To perform this operation, call FltFsControlFile or ZwFsControlFile with the following parameters.
Instance [in]: FltFsControlFile only. Opaque instance pointer for the caller. This parameter is required and cannot be NULL.
FileObject [in]: FltFsControlFile only. The file object pointer to the file which has the data to be trimmed. This parameter is required and cannot be NULL.
FileHandle [in]: ZwFsControlFile only. The file handle of the file which has the data to be trimmed. This parameter is required and cannot be NULL.
FsControlCode [in]: Control code for the operation. Use FSCTL_FILE_LEVEL_TRIM for this operation.
InputBuffer [in]: A pointer to a FILE_LEVEL_TRIM structure which contains an array of trim ranges for the file.
InputBufferLength [in]: Size, in bytes, of the buffer pointed to by the InputBuffer parameter. This value must be at least sizeof(FILE_LEVEL_TRIM).
OutputBuffer [out]: A pointer to an optional FILE_LEVEL_TRIM_OUTPUT structure which receives the result of the trim operation.
OutputBufferLength [out]: Size, in bytes, of the buffer pointed to by the OutputBuffer parameter. This value must be at least sizeof(FILE_LEVEL_TRIM_OUTPUT) if FILE_LEVEL_TRIM_OUTPUT is included in OutputBuffer. Otherwise, this is set to 0.
FltFsControlFile or ZwFsControlFile returns STATUS_SUCCESS or possibly one of the following values.
| Code | Meaning |
|---|---|
| STATUS_INVALID_PARAMETER | The file to trim is either compressed or encrypted, the input or output buffer length is invalid, or, no trim ranges are specified. |
| STATUS_INSUFFICIENT_RESOURCES | An internal resource allocation failed. |
| STATUS_FILE_LOCK_CONFLICT | A trim range is part of a previously locked byte range. |
| STATUS_VOLUME_DISMOUNTED | The volume where the file resides is not mounted. |
| STATUS_PURGE_FAILED | A cache purge failed for a trim range. |
| STATUS_NO_RANGES_PROCESSED | No ranges in the trim range array were processed. |
Performing trim on certain storage devices can significantly improve their future write performance. Trim also returns resources to the allocation pool in storage systems that are thinly provisioned. When files are deleted on a virtual disk, the size of the virtual disk file itself is not changed. The data ranges freed on the virtual disk are not trimmed on the physical storage where the virtual disk file resides. A virtual disk device can notify the file system that certain data ranges in a virtual disk file can be trimmed on the physical storage device with an FSCTL_FILE_LEVEL_TRIM request. The file system will then issue a trim request to the physical storage. An FSCTL_FILE_LEVEL_TRIM request could also be issued by service applications managing database or memory swap files.
The FSCTL_FILE_LEVEL_TRIM control code will attempt to trim the selected byte ranges of a file from a storage device. The byte ranges are contained in the Ranges array in the FILE_LEVEL_TRIM structure. Included in the Ranges array are one or more FILE_LEVEL_TRIM_RANGE structures.
Including overlapping ranges in the range array is not necessarily an error condition. This is dependent on how extent processing is handled by the underlying storage.
Trimmed ranges are purged as pages from the file system cache. In order to match the cache page size, a trim range's length is adjusted down to a multiple of PAGE_SIZE. Also, if a trim range offset does not begin at a page boundary, it is aligned to the next page boundary. With these constraints, trim range lengths will reduce when their offsets are not page aligned or lengths are not a page size multiple. A trim range length may reduce to 0 if the original length is less than two pages and the offset is not page aligned.
If a trim range is specified or page adjusted beyond the end-of-file (EOF), the range is ignored. However, a range offset aligned before EOF but having a length extending past EOF will be adjusted to a page size multiple <= EOF.
File level trim is not supported for compressed or encrypted files (files with ATTRIBUTE_FLAG_COMPRESSION_MASK or ATTRIBUTE_FLAG_ENCRYPTED attributes set).
A file trim is performed outside of any transaction. The trim operation cannot be rolled back.
With sparse files (files with the ATTRIBUTE_FLAG_SPARSE attribute set), a trim range in an unallocated portion of the file is ignored.
When included in OutputBuffer, the NumRangesProcessed member of the FILE_LEVEL_TRIM_OUTPUT will indicate the number of trim ranges successfully processed. If an error occurs during the processing of the trim ranges, NumRangesProcessed will specify the starting index of the remaining unprocessed ranges, ending at the NumRanges member of FILE_LEVEL_TRIM - 1.
| Requirement type | Requirement |
|---|---|
| Minimum supported client | Windows 8 |
| Header | Ntifs.h (include Ntifs.h or Fltkernel.h) |