Performing storage driver data set management
Starting with Windows 7, drivers can perform management actions on a device's data set. The list of data set management (DSM) actions that can be performed on a storage device are defined by Microsoft.
Using IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES
A DEVICE_DSM_ACTION constant specifies the action. This constant is passed in the Action member of the DEVICE_DSM_INPUT structure contained in the system buffer of an IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES request. If the action requires additional parameters, a parameter block will immediately follow the DEVICE_DSM_INPUT structure, and ParameterBlockOffset will specify the offset from the start of the DEVICE_DSM_INPUT structure at which the parameter block starts. Data set ranges, if any, will immediately follow the parameter block, and DataSetRangesOffset will specify the offset from the start of the DEVICE_DSM_INPUT structure at which the range(s) starts. The system buffer structure is shown in the following diagram.
If the management action will return output, a pointer to a DEVICE_DSM_OUTPUT structure is passed in the IOCTL's OutputBuffer. If the action will return additional action-specific output, an output block will immediately follow the DEVICE_DSM_OUTPUT structure, and OutputBlockOffset will specify the offset from the start of the DEVICE_DSM_OUTPUT structure at which the parameter block starts. The output buffer structure is shown in the following diagram.
Process flow of a DSM action
The process flow of a DSM action is described below, where Sender is the action requestor and Handler processes the requested action. Note that there can be more than one Handler in the stack.
Sender initializes the DSM and sends it to the first Handler in the stack by doing the following:
- Allocate and initialize a DEVICE_DSM_DEFINITION structure with the definition associated with the action.
- Call DeviceDsmGetInputLength to determine the size required for the action's input buffer, and then allocate memory for this buffer.
- Call DeviceDsmInitializeInput to initialize the DSM_DEVICE_INPUT structure and, if the action has parameters, the parameter block. The parameter block format depends on the action. See DEVICE_DSM_ACTION Descriptions for more details.
- If the action has ranges, call DeviceDsmAddDataSetRange for each range to add DEVICE_DSM_RANGE structure(s) to the input buffer.
- If the DSM has output, call DeviceDsmGetOutputLength to determine the size required for the action's output buffer, and then allocate memory for this buffer.
- Send an IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES request, passing the initialized input data in the IOCTL's system buffer, along with the allocated output buffer, if any.
Handler handles the DSM IOCTL request in one of three ways:
- Handle the request and return with output, if any.
- Handle the request and forward it to the next lower driver in the stack.
- Forward the request to the next lower driver in the stack without handling the DSM.
Note
Regardless of whether the driver handles the DSM, it can safely forward the request only if DEVICE_DSM_ACTION's most significant bit (DeviceDsmActionFlag_NonDestructive) is set. If DeviceDsmActionFlag_NonDestructive is not set, the driver should instead return with an error.
If Handler does handle the DSM, it performs the following steps:
- Validate the input by calling DeviceDsmValidateInput.
- If the input is valid, Handler extracts the input to get the action. If the action has a parameter block, Handler calls DeviceDsmParameterBlock to get the parameter block. If the action has range data, Handler calls DeviceDsmDataSetRanges to get a pointer to the block of data set ranges, and then performs the normal processing on the block. This block is located at DataSetRangesOffset and consists of one or more contiguous entries formatted as DEVICE_DSM_RANGE structures. The length, in bytes, of the data set ranges is set in the DataSetRangesLength member of DEVICE_DSM_INPUT.
- If the action requires output, Handler calls DeviceDsmValidateOutputLength to validate the sender-supplied output buffer. If valid, the handler initializes the DEVICE_DSM_OUTPUT portion of the output buffer by calling DeviceDsmInitializeOutput, and populates the output block with action-specific output, if any. The Handler then completes the IOCTL and either returns or forwards the IOCTL to the next driver in the stack.
Once the DSM is handled and returned to the Sender, the Sender validates the output, if any, by calling DeviceDsmValidateOutput. If the output is valid, Sender extracts the output block, if any, by calling DeviceDsmOutputBlock.
For details on each specific DSM action, see Device DSM Action Descriptions.